displaying a message in angular 6 - chat

hello I'm learning angular 6 but I don't understand why it doesn't display my message but he appears in the logs of my server.
component:
import { Component } from '#angular/core';
import { ChatService } from '../chat.service';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
message: string;
messages: string[] = [];
constructor(private chatService: ChatService) {
}
sendMessage() {
this.chatService.sendMessage(this.message);
this.message = '';
}
OnInit() {
this.chatService
.getMessages()
.subscribe((message: string) => {
this.messages.push(message);
});
}
}
html:
<div>
<li *ngFor="let message of messages">
{{message}}
</li>
</div>
<input [(ngModel)]="message" (keyup)="$event.keyCode == 13 && sendMessage()" />
<button (click)="sendMessage()">Send</button>
thanks for your help

chat service :
import * a io from 'socket.io-client';
import {Observable} from 'rxjs';
export class ChatService{
private url = 'http://localhost:3000';
private socket;
constructor() {
this.socket = io(this.url);
}
public sendMessage(message){
this.socket.emit('new-message',message);
}
public getMessage = () => {
return Observable.create((observer) => {
this.socket.on('new-message' , (message) => {
observer.next(message);
});
});
}
}

Related

How to creat a dynamic text

I have a list of titles, and I would like these texts to alternate as I switch to ion-select. How do I do this?
I have no idea how to do this, not even what part of the code to show. I made an attempt here but whenever I use the console the value returned is undefined.
My typescrit code:
import { Titulo } from './../Services/services.service';
import { DataService } from './data.service';
import { Component, OnInit, ViewChild} from '#angular/core';
import {IonSlides} from '#ionic/angular';
import { ActivatedRoute } from '#angular/router';
#Component({
selector: 'app-libertacao',
templateUrl: './libertacao.page.html',
styleUrls: ['./libertacao.page.scss'],
})
export class LibertacaoPage implements OnInit {
#ViewChild(IonSlides) slides: IonSlides;
PAGINA_SELECIONADA: number;
// tslint:disable-next-line: variable-name
index_atual: number;
titulo: Titulo;
constructor(private dataservice: DataService, private activatedRoute: ActivatedRoute ){
}
ngOnInit() {
const id = this.activatedRoute.snapshot.paramMap.get('id');
this.titulo = this.dataservice.getTituloById(parseInt(id, 10));
}
OnChange(event: any)
{
if (event.detail.value === this.PAGINA_SELECIONADA) {
this.slides.slideTo(this.PAGINA_SELECIONADA);
}
else {}
console.log(this.titulo);
}
slideChanged() {
this.slides.getActiveIndex().then((index) => {
this.index_atual = index;
});
}
}

Why not showing liked icon when page refresh in ionic

I am making like and dislike functionality in ionic app when user like then want to show heart icon and when user dislike then want to show empty heart icon.When like the post then icon show but when refreshing page then its show icon of empty likes.Please help me how to resolve this problem in ionic....
tab1.page.html
<div>
<img src="{{getImage.image}}" (click)="tapPhotoLike(getImage.id)" (click)="toggleIcon(getImage.id)">
</div>
<p no-margin no-padding>
<button clear ion-button icon-only class="like-btn">
<!-- <ion-icon no-padding name="like_btn.icon_name" color="{{ like_btn.color }}" class="icon-space"></ion-icon> -->
<ion-icon name="heart-empty" *ngIf="!iconToggle[getImage.id]" color="{{ like_btn.color }}"></ion-icon>
<ion-icon name="heart" *ngIf="iconToggle[getImage.id]" color="{{ like_btn.color }}"></ion-icon>
</button>
</p>
tab1.page.ts
import { Component, OnInit } from '#angular/core';
import { UserService } from '../user.service';
import { User } from '../user';
import { first } from 'rxjs/operators';
import { Storage } from '#ionic/storage';
import { ToastController } from '#ionic/angular';
import { LoadingController, NavController } from '#ionic/angular';
#Component({
selector: 'app-tab1',
templateUrl: 'tab1.page.html',
styleUrls: ['tab1.page.scss']
})
export class Tab1Page implements OnInit {
num
getImages: User[] = [];
getImages2: User[] = [];
getImages3 = [];
getcounts;
countLikes
counts
unlikes
likesID
iconToggle = [];
like_btn = {
color: 'danger',
icon_name: 'heart-empty'
};
public tap: number = 0;
public status: false;
constructor(private userService: UserService,
public toastController: ToastController,
private storage: Storage,
public navCtrl: NavController,
public loadingController: LoadingController) {
}
doRefresh(event) {
this.userPost();
setTimeout(() => {
event.target.complete();
}, 2000);
}
ngOnInit() {
this.userPost();
//this.getCountOfLikes();
}
async userPost() {
const loading = await this.loadingController.create({
message: 'Please wait...',
spinner: 'crescent',
duration: 2000
});
await loading.present();
this.userService.getUserPost().pipe(first()).subscribe(getImages => {
this.getImages3 = getImages;
loading.dismiss();
});
}
likeButton() {
const detail_id = this.userService.getCurrentIdpostId();
this.storage.get('userId').then((val) => {
if (val) {
let user_id = val
this.userService.userPostLikes(user_id, detail_id).pipe(first()).subscribe(
async data => {
this.iconToggle[this.num] = true;
if (data['status'] === 'you have already liked this post') {
const toast = await this.toastController.create({
message: 'you have already liked this post before.',
duration: 2000
});
toast.present();
}
this.userPost();
}
);
}
});
}
tapPhotoLike($detail_id, num) {
this.userService.setCurrentIdpostId($detail_id);
this.tap++;
setTimeout(() => {
if (this.tap == 1) {
this.tap = 0;
//this.unlikePost();
} if (this.tap > 1) {
this.tap = 0;
}
}, 250);
}
setIconToggles() {
let x = 0;
this.getImages3.forEach(() => {
this.iconToggle[x] = false;
x++;
});
}
toggleIcon(num) {
if (this.iconToggle[num]) {
this.iconToggle[num] = false;
this.unlikePost();
} else {
this.iconToggle[num] = true;
this.likeButton();
}
}
ionViewWillEnter() {
this.userPost();
}
unlikePost() {
let detail_id = this.userService.getCurrentIdpostId();
this.storage.get('userId').then((val) => {
if (val) {
let user_id = val;
this.userService.unLikes(user_id, detail_id).subscribe(async dislikes => {
this.unlikes = dislikes;
this.iconToggle[this.num] = false;
this.userPost();
})
}
});
}
}
How manage icon , i am inserting status on like and dislike in database..In this code how to manage status please help me.

ERROR TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable

I'm working on autocomplete-search with angular 4. This search bar will get books information from Google Books API. It works fine when I input any search terms. But it causes an error if I remove the entire search term or input a space.This is the error I got
This is my SearchComponent.ts
import { Component, OnInit } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
#Component({
selector: 'app-admin-search',
templateUrl: './admin-search.component.html',
styleUrls: ['./admin-search.component.css']
})
export class AdminSearchComponent implements OnInit {
books: any[] = [];
searchTerm$ = new Subject<string>();
constructor (private bookService: BookService,
private http: HttpClient
) {
this.bookService.search(this.searchTerm$)
.subscribe(results => {
this.books = results.items;
});
}
ngOnInit() {
}
This is my SearchComponent.html
<div>
<h4>Book Search</h4>
<input #searchBox id="search-box"
type="text"
placeholder="Search new book"
(keyup)="searchTerm$.next($event.target.value)"/>
<ul *ngIf="books" class="search-result">
<li *ngFor="let book of books">
{{ book.volumeInfo.title }}
</li>
</ul>
</div>
This is my BookService.ts
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Book } from './book';
import { BOOKS } from './mock-books';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/switchMap';
#Injectable()
export class BookService {
private GoogleBookURL: string = "https://www.googleapis.com/books/v1/volumes?q=";
constructor (private http: HttpClient) { }
search(terms: Observable<string>) {
return terms.debounceTime(300)
.distinctUntilChanged()
.switchMap(term => this.searchEntries(term));
}
searchEntries(searchTerm: string) {
if (searchTerm.trim()) {
searchTerm = searchTerm.replace(/\s+/g, '+');
let URL = this.GoogleBookURL + searchTerm;
return this.http.get(URL);
}
}
}
Can someone help me out? Thanks in advance!
Your method searchEntries returns value (Observable<Response>) only if searchTerm.trim() is true (so it must return non-empty string).
There can be situation that searchEntries will return undefined instead of Obervable<Response> if trim() returns '' (empty string which is false). You can't pass undefined returned from searchEntries into .switchMap(term => this.searchEntries(term));.
For that case your code will look like this:
.switchMap(term => undefined) which is not valid construction.

Angular2 SPA (REST API) basic get (CRUD)

Good Morning,
I have my back-end working beautifully but just can’t finish off the front!
I'm confident in my ability to config the back however when I load my desired page I just can’t display my data.
Would someone please advise or direct to a tutorial?
This is what I'm currently using to assist: Angular-2-crud
Thanks GWS
cashmovement-list.component.ts
import { Component, OnInit, ViewChild, Input, Output, trigger, state, style, animate, transition } from '#angular/core';
import { ModalDirective } from 'ng2-bootstrap';
import { DataService } from '../shared/services/data.service';
import { DateFormatPipe } from '../shared/pipes/date-format.pipe';
import { ItemsService } from '../shared/utils/items.service';
import { NotificationService } from '../shared/utils/notification.service';
import { ConfigService } from '../shared/utils/config.service';
import { ICashMovement, Pagination, PaginatedResult } from '../shared/interfaces';
#Component({
moduleId: module.id,
selector: 'cashmovements',
templateUrl: 'cashmovement-list.component.html'
})
export class CashMovementListComponent implements OnInit {
public cashmovements: ICashMovement[];
constructor(private dataService: DataService,
private itemsService: ItemsService,
private notificationService: NotificationService) { }
ngOnInit() {
this.dataService.getCashMovements()
.subscribe((cashmovements: ICashMovement[]) => {
this.cashmovements = cashmovements;
},
error => {
this.notificationService.printErrorMessage('Failed to load users. ' + error);
});
}
}
cashmovement-list.component.html
<button class="btn btn-primary" type="button" *ngIf="cashmovements">
<i class="fa fa-calendar" aria-hidden="true"></i> CashMovements
<span class="badge">{{totalItems}}</span>
</button>
<hr/>
<div [#flyInOut]="'in'">
<table class="table table-hover">
<thead>
<tr>
<th><i class="fa fa-text-width fa-2x" aria-hidden="true"></i>Cash Movement ID</th>
<th><i class="fa fa-user fa-2x" aria-hidden="true"></i>PortfolioCode</th>
<th><i class="fa fa-paragraph fa-2x" aria-hidden="true"></i>CCY Out</th>
<th><i class="fa fa-map-marker fa-2x" aria-hidden="true"></i>Account Out</th>
<th><i class="fa fa-calendar-o fa-2x" aria-hidden="true"></i>Date</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let cashmovement of cashmovements">
<td> {{cashmovement.CashMovementId}}</td>
<td>{{cashmovement.PortfolioCode}}</td>
<td>{{cashmovement.Ccyo}}</td>
<td>{{cashmovement.AccountO}}</td>
<td>{{cashmovement.Date | dateFormat | date:'medium'}}</td>
</tr>
</tbody>
</table>
</div>
interfaces.ts
export interface ICashMovement {
CashMovementId: number;
PortfolioCode: string;
Date: Date;
Ccyo: string;
AccountO: string;
ValueO: number;
Ccyi: string;
AccountI: string;
ValueI: number;
status: string;
comment: string;
LastUpdate: number;
}
app.module.ts
import './rxjs-operators';
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms';
import { HttpModule } from '#angular/http';
import { PaginationModule } from 'ng2-bootstrap/ng2-bootstrap';
import { DatepickerModule } from 'ng2-bootstrap/ng2-bootstrap';
import { Ng2BootstrapModule } from 'ng2-bootstrap/ng2-bootstrap';
import { ModalModule } from 'ng2-bootstrap/ng2-bootstrap';
import { ProgressbarModule } from 'ng2-bootstrap/ng2-bootstrap';
import { SlimLoadingBarService, SlimLoadingBarComponent } from 'ng2-slim- loading-bar';
import { TimepickerModule } from 'ng2-bootstrap/ng2-bootstrap';
import { AppComponent } from './app.component';
import { DateFormatPipe } from './shared/pipes/date-format.pipe';
import { HighlightDirective } from './shared/directives/highlight.directive';
import { HomeComponent } from './home/home.component';
import { MobileHideDirective } from './shared/directives/mobile-hide.directive';
import { CashMovementListComponent } from './cashmovements/cashmovement-list.component';
import { routing } from './app.routes';
import { DataService } from './shared/services/data.service';
import { ConfigService } from './shared/utils/config.service';
import { ItemsService } from './shared/utils/items.service';
import { MappingService } from './shared/utils/mapping.service';
import { NotificationService } from './shared/utils/notification.service';
#NgModule({
imports: [
BrowserModule,
DatepickerModule,
FormsModule,
HttpModule,
Ng2BootstrapModule,
ModalModule,
ProgressbarModule,
PaginationModule,
routing,
TimepickerModule
],
declarations: [
AppComponent,
DateFormatPipe,
HighlightDirective,
HomeComponent,
MobileHideDirective,
SlimLoadingBarComponent,
CashMovementListComponent
],
providers: [
ConfigService,
DataService,
ItemsService,
MappingService,
NotificationService,
SlimLoadingBarService
],
bootstrap: [AppComponent]
})
export class AppModule { }
data.service.ts
import { Injectable } from '#angular/core';
import { Http, Response, Headers } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import {Observer} from 'rxjs/Observer';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { ICashMovement, Pagination, PaginatedResult } from '../interfaces';
import { ItemsService } from '../utils/items.service';
import { ConfigService } from '../utils/config.service';
#Injectable()
export class DataService {
_baseUrl: string = '';
constructor(private http: Http,
private itemsService: ItemsService,
private configService: ConfigService) {
this._baseUrl = configService.getApiURI();
}
getCashMovements(): Observable<ICashMovement[]> {
return this.http.get(this._baseUrl + 'cashmovements')
.map((res: Response) => { return res.json(); })
.catch(this.handleError);
}
private handleError(error: any) {
var applicationError = error.headers.get('Application-Error');
var serverError = error.json();
var modelStateErrors: string = '';
if (!serverError.type) {
console.log(serverError);
for (var key in serverError) {
if (serverError[key])
modelStateErrors += serverError[key] + '\n';
}
}
modelStateErrors = modelStateErrors = '' ? null : modelStateErrors;
return Observable.throw(applicationError || modelStateErrors || 'Server error');
}
}
I think the problem might be in your templateUrl. You need to prefix the partial view with ./ regardless of whether you use moduleId. You need to specify templateUrl: "./cashmovement-list.component.html"
However, if you are getting any error in the dve console of your browser you should post it as an uplate to your question.

How to use Bootstrap accordion with angular2 (HTML5 mode/hashbag in angular2)

I'm trying to use bootstrap accordion but both (angular2 and bootstrap accordian) plays around hash location.
So is there something like html5 mode in angular2?
try this
/// <reference path="../../../typings/tsd.d.ts" />
import {
Component, View,
Directive, LifecycleEvent,
EventEmitter, ElementRef,
CSSClass, ViewContainerRef, TemplateRef
} from 'angular2/angular2';
// todo: support template url
#Component({
selector: 'accordion, [accordion]',
properties: [
'templateUrl',
'bCloseOthers: closeOthers'
]
})
#View({
template: `
<div class="panel-group">
<ng-content></ng-content>
</div>
`
})
export class Accordion {
private templateUrl:string;
private bCloseOthers:any;
private groups:Array<any> = [];
constructor() {
}
public closeOthers(openGroup:AccordionGroup) {
if (!this.bCloseOthers) {
return;
}
this.groups.forEach((group:AccordionGroup) => {
if (group !== openGroup) {
group.isOpen = false;
}
});
}
public addGroup(group:AccordionGroup) {
this.groups.push(group);
}
public removeGroup(group:AccordionGroup) {
let index = this.groups.indexOf(group);
if (index !== -1) {
this.groups.slice(index, 1);
}
}
}
#Directive({
selector: 'accordion-transclude, [accordion-transclude]',
properties: ['headingTemplate: accordion-transclude'],
lifecycle: [LifecycleEvent.onInit]
})
export class AccordionTransclude {
private headingTemplate: TemplateRef;
constructor(private viewRef: ViewContainerRef) {
}
onInit() {
if (this.headingTemplate) {
this.viewRef.createEmbeddedView(this.headingTemplate);
}
}
}
import {Collapse} from '../collapse/collapse';
// todo: support template url
// todo: support custom `open class`
#Component({
selector: 'accordion-group, [accordion-group]',
properties: [
'templateUrl',
'heading',
'isOpen',
'isDisabled'
],
host: {
'[class.panel-open]': 'isOpen'
},
lifecycle: [LifecycleEvent.onInit, LifecycleEvent.onDestroy]
})
#View({
template: `
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a href tabindex="0" class="accordion-toggle"
(^click)="toggleOpen($event)">
<span [class]="{'text-muted': isDisabled}"
[accordion-transclude]="headingTemplate">{{heading}}</span>
</a>
</h4>
</div>
<div class="panel-collapse collapse" [collapse]="!isOpen">
<div class="panel-body">
<ng-content></ng-content>
</div>
</div>
</div>
`,
directives: [Collapse, AccordionTransclude, CSSClass]
})
export class AccordionGroup {
private templateUrl:string;
private _isOpen:boolean;
public isDisabled:boolean;
public headingTemplate:any;
public templateRef: any;
constructor(private accordion:Accordion) {
}
onInit() {
this.accordion.addGroup(this);
}
onDestroy() {
this.accordion.removeGroup(this);
}
public toggleOpen(event:MouseEvent) {
event.preventDefault();
if (!this.isDisabled) {
this.isOpen = !this.isOpen;
}
}
public get isOpen():boolean {
return this._isOpen;
}
public set isOpen(value:boolean) {
this._isOpen = value;
if (value) {
this.accordion.closeOthers(this);
}
}
}
#Directive({
selector: 'accordion-heading, [accordion-heading]'
})
export class AccordionHeading {
constructor(private group:AccordionGroup, private templateRef: TemplateRef) {
group.headingTemplate = templateRef;
}
}
export const accordion:Array<any> = [
Accordion, AccordionGroup,
AccordionHeading, AccordionTransclude];