26. Cookbook Recipes
Parent Child Component Interaction:
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-article',
template: `
<p>{{ currentDate | date }}</p>
<h1>{{ title }}</h1>
<app-attribution [author]="author"></app-attribution>
`,
styles: []
})
export class ArticleComponent {
currentDate: Date;
title: string;
author: string;
constructor() {
this.currentDate = new Date();
this.title = `The Will to Win is nothing without the Will to Prepare`;
this.author = 'Nils- Holger';
}
}
@Component({
selector: 'app-attribution',
template: `
<h3>Written by: {{ author }}</h3>
`,
styles: [``]
})
export class AttributionComponent {
@Input() author: string;
}
Binding to Native Element Attribute:
import { Component } from '@angular/core';
@Component({
selector: 'app-polymer-princess',
template: `
<img [src]="imgURL">
`,
styles: [`
img {
border-radius: 100%;
width: 600px;
}
`]
})
export class PolymerPrincessComponent {
imgURL = './assets/carmen1.jpg';
}
Registering handlers on native browser events:
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-article',
template: `
<h1>{{ title }}</h1>
<p>Shares: {{ shareCount }}</p>
<button (click)="share($event)">Share</button>
`,
styles: []
})
export class ArticleComponent {
title = 'I have met my hero, he is me.';
shareCount = 0;
share(e: Event): void {
console.log(e);
++this.shareCount;
}
}
Generating and capturing custom events using EventEmitter:
import { Component, Input, EventEmitter, Output} from '@angular/core';
@Component({
selector: 'app-text-editor',
template: `
<textarea (keyup)="emitWordCount($event)"></textarea>
`
})
export class TextEditorComponent {
@Output() countUpdate = new EventEmitter<number>();
emitWordCount(e): void {
this.countUpdate.emit(e.target.value.match(/\S+/g || []).length);
}
}
@Component({
selector: 'app-article',
template: `
<h1>{{ title }}</h1>
<p>Word count: {{ wordCount }}</p>
<app-text-editor (countUpdate)="updateWordCount($event)"></app-text-editor>
`,
styles: []
})
export class ArticleComponent {
title = 'I have met my hero, he is me.';
wordCount = 0;
updateWordCount(e: number): void {
this.wordCount = e;
}
}
Directive behavior DOM elements:
import { Component, Directive, HostListener } from '@angular/core';
@Directive({
selector: '[appMouseOverToReveal]'
})
export class ClickToRevealDirective {
@HostListener('mouseover', ['$event.target'])
reveal(target) {
target.style['white-space'] = 'normal';
}
}
@Component({
selector: 'app-article',
template: `
<h1 appMouseOverToReveal>{{ title }}</h1>
`,
styles: [`
h1 {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
max-width: 300px;
}
`]
})
export class ArticleComponent {
title = 'The will to win is nothing without the will to prepare.';
}
Projecting nested content using ng-content:
import { Component } from '@angular/core';
@Component({
selector: 'app-ad-section',
template: `
<a href="#">{{ adText }}</a>
<ng-content select="p"></ng-content>
`
})
export class AdSectionComponent {
adText = 'Angular 5 Love Affair';
}
@Component({
selector: 'app-article',
template: `
<h1>{{ title }}</h1>
<app-ad-section>
<p>It is at the borders of pain that the men are separated from the boys.</p>
<p>Somebody may beat me but they will have to bleed to do it.</p>
</app-ad-section>
`,
styles: [``]
})
export class ArticleComponent {
title = 'The will to win is nothing without the will to prepare.';
}
ngFor && ngIf:
import { Component } from '@angular/core';
@Component({
selector: 'app-article-list',
template: `
<div *ngFor="let article of articles; let i = index;">
<h1 *ngIf="article.active">
{{ i + 1 }}: {{ article.title }}
</h1>
</div>
`
})
export class ArticleListComponent {
articles: Array<Object> = [
{ title: 'Angular 5 to save the world', active: true },
{ title: 'Angular CLI 1.6', active: false },
{ title: 'Angular Material 5 CSS Design Framework', active: true }
];
}
Desugared:
import { Component } from '@angular/core';
@Component({
selector: 'app-article-list',
template: `
<ng-template ngFor let-article [ngForOf]="articles" let-i="index">
<div>
<ng-template [ngIf]="article.active">
<h1>
{{ i + 1 }}: {{ article.title }}
</h1>
</ng-template>
</div>
</ng-template>
`
})
export class ArticleListComponent {
articles: Array<Object> = [
{ title: 'Angular 5 to save the world', active: true },
{ title: 'Angular CLI 1.6', active: true },
{ title: 'Angular Material 5 CSS Design Framework', active: false }
];
}
Template Reference Variable:
@Component({
selector: 'app-article',
template: `
<input #title (keyup)="0">
<h1>{{ title.value }}</h1>
`,
styles: [``]
})
export class ArticleComponent {
}
@Component({
selector: 'app-article',
template: `
<input #title (keyup)="setTitle(title.value)">
<h1>{{ myTitle }}</h1>
`,
styles: [``]
})
export class ArticleComponent {
myTitle = '';
setTitle(val: string): void {
this.myTitle = val;
}
}
Lifecycle Hooks:
import { Component, Input, OnInit, OnDestroy } from '@angular/core';
@Component({
selector: 'app-article-list',
template: `
<input type="text" (keyup.enter)="add($event)">
<app-article *ngFor="let title of titles; let i = index;"
[articleTitle]="title">
<button (click)="remove(i)">X</button>
<app-article>
`
})
export class ArticleListComponent {
titles: Array<string> = [];
add(e): void {
this.titles.push(e.target.value);
e.target.value = '';
}
remove(index: number) {
this.titles.splice(index, 1);
}
}
@Component({
selector: 'app-article',
template: `
<div>
{{ articleTitle }}<ng-content></ng-content>
</div>
`,
styles: [``]
})
export class ArticleComponent implements OnInit, OnDestroy {
@Input() articleTitle: string;
ngOnInit() {
console.log('created', this.articleTitle);
}
ngOnDestroy() {
console.log('destroyed', this.articleTitle);
}
}
Referencing Parent Component in Child Component:
@Component({
selector: 'app-article',
template: `
<app-feedback [val]="likes"></app-feedback>
`,
styles: [``]
})
export class ArticleComponent {
likes = 0;
incrementLikes(): void {
this.likes++;
}
}
@Component({
selector: 'app-feedback',
template: `
<h1>Number of likes: {{ val }}</h1>
<button (click)="likeArticle()">Like this article</button>
`
})
export class FeedbackComponent {
@Input() val: number;
private articleComponent: ArticleComponent;
constructor(articleComponent: ArticleComponent) {
this.articleComponent = articleComponent;
}
likeArticle(): void {
this.articleComponent.incrementLikes();
}
}
ViewChild && forwardRef:
import { Component, Input, Inject,
forwardRef, ViewChild, AfterViewInit } from '@angular/core';
@Component({
selector: 'app-feedback',
template: `
<h1>Number of likes: {{ val }}</h1>
<button (click)="likeArticle()"
[disabled]="!likeEnabled">
Like this article!
</button>
`
})
export class FeedbackComponent {
@Input() val: number;
private likeEnabled = false;
private articleComponent: ArticleComponent;
constructor(@Inject(forwardRef(() => ArticleComponent))
articleComponent: ArticleComponent) {
this.articleComponent = articleComponent;
}
likeArticle(): void {
this.articleComponent.incrementLikes();
}
setLikeEnabled(newEnabledStatus: boolean): void {
this.likeEnabled = newEnabledStatus;
}
}
@Component({
selector: 'app-article',
template: `
<input type="checkbox" (click)="changeLikesEnabled($event)">
<app-feedback [val]="likes"></app-feedback>
`,
styles: [``]
})
export class ArticleComponent implements AfterViewInit {
@ViewChild(FeedbackComponent) feedbackComponent: FeedbackComponent;
likes = 0;
constructor() {
console.log(this.feedbackComponent);
}
ngAfterViewInit() {
console.log(this.feedbackComponent);
}
incrementLikes(): void {
this.likes++;
}
changeLikesEnabled(e): void {
this.feedbackComponent.setLikeEnabled(e.target.checked);
}
}
ContentChild && forwardRef:
import { Component, ContentChild,
Inject, forwardRef, AfterContentInit } from '@angular/core';
@Component({
selector: 'app-feedback',
template: `
<h1>Number of likes: {{ val }}</h1>
<button (click)="likeArticle()"
[disabled]="!likeEnabled">
Like this article!
</button>
`
})
export class FeedbackComponent {
private val: number;
private likeEnabled = false;
private articleComponent: ArticleComponent;
constructor(@Inject(forwardRef(() => ArticleComponent))
articleComponent: ArticleComponent) {
this.articleComponent = articleComponent;
}
updateLikes() {
this.val = this.articleComponent.likes;
}
likeArticle(): void {
this.articleComponent.incrementLikes();
this.updateLikes();
}
setLikeEnabled(newEnabledStatus: boolean): void {
this.likeEnabled = newEnabledStatus;
}
}
@Component({
selector: 'app-article',
template: `
<input type="checkbox" (click)="changeLikesEnabled($event)">
<ng-content></ng-content>
`,
styles: [``]
})
export class ArticleComponent implements AfterContentInit {
@ContentChild(FeedbackComponent) feedbackComponent: FeedbackComponent;
likes = 0;
constructor() {
console.log(this.feedbackComponent);
}
ngAfterContentInit() {
console.log(this.feedbackComponent);
}
incrementLikes(): void {
this.likes++;
}
changeLikesEnabled(e): void {
this.feedbackComponent.setLikeEnabled(e.target.checked);
}
}
ngModel:
import { Component } from '@angular/core';
@Component({
selector: 'app-article-editor',
template: `
<input [(ngModel)]="title">
<input [(ngModel)]="title">
<h2>{{ title }}</h2>
`
})
export class ArticleEditorComponent {
title = '';
}
@Component({
selector: 'app-article-editor',
template: `
<input [ngModel]="title" (ngModelChange)="title=$event">
<input [ngModel]="title" (ngModelChange)="title=$event">
<h2>{{ title }}</h2>
`
})
export class ArticleEditorComponent {
title = '';
}
@Component({
selector: 'app-article-editor',
template: `
<input [value]="title" (input)="title=$event.target.value">
<input [value]="title" (input)="title=$event.target.value">
<h2>{{ title }}</h2>
`
})
export class ArticleEditorComponent {
title = '';
}
import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';
@Component({
selector: 'app-article-editor',
template: `
<p>Article title (required)</p>
<input [formControl]="titleControl" required>
<button (click)="submitTitle()">Save</button>
<h1>{{ title }}</h1>
`
})
export class ArticleEditorComponent {
title = '';
titleControl: FormControl = new FormControl();
submitTitle(): void {
if (this.titleControl.valid) {
this.title = this.titleControl.value;
} else {
console.log('Title required');
}
}
}
import { Component } from '@angular/core';
import { FormControl, Validators } from '@angular/forms';
@Component({
selector: 'app-article-editor',
template: `
<p>Article title (required)</p>
<input [formControl]="titleControl">
<button (click)="submitTitle()">Save</button>
<h1>{{ title }}</h1>
`
})
export class ArticleEditorComponent {
title = '';
titleControl: FormControl = new FormControl(null, Validators.required);
submitTitle(): void {
if (this.titleControl.valid) {
this.title = this.titleControl.value;
} else {
console.log('Title required');
}
}
}
import { Component } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-article-editor',
template: `
<p>Title: <input [formControl]="titleControl"></p>
<p>Text: <input [formControl]="textControl"></p>
<p><button (click)="saveArticle()">Save</button></p>
<hr>
<p>Preview:</p>
<div style="border: 1px solid #999; margin: 50px;">
<h1>{{ article.title }}</h1>
<p>{{ article.text }}</p>
</div>
`
})
export class ArticleEditorComponent {
article: {title: string, text: string } = {title: '', text: ''};
titleControl = new FormControl(null, Validators.required);
textControl = new FormControl(null, Validators.required);
articleFormGroup = new FormGroup({
title: this.titleControl,
text: this.textControl
});
saveArticle(): void {
if (this.articleFormGroup.valid) {
this.article = this.articleFormGroup.value;
} else {
console.log('Missing field(s)!');
}
}
}
import { Component } from '@angular/core';
import { FormControl, FormArray, Validators } from '@angular/forms';
@Component({
selector: 'app-article-editor',
template: `
<p>Tags:</p>
<ul>
<li *ngFor="let t of tagControls; let i = index;">
<input [formControl]="t">
<button (click)="removeTag(i)">X</button>
</li>
</ul>
<p><button (click)="addTag()">+</button></p>
<p><button (click)="saveArticle()">Save</button></p>
`
})
export class ArticleEditorComponent {
tagControls: Array<FormControl> = [];
tagFormArray: FormArray = new FormArray(this.tagControls);
addTag(): void {
this.tagFormArray.push(new FormControl(null, Validators.required));
}
removeTag(idx: number): void {
this.tagFormArray.removeAt(idx);
}
saveArticle(): void {
if (this.tagFormArray.valid) {
console.log('Valid');
} else {
console.log('Missing field(s)');
}
}
}
import { Component } from '@angular/core';
import { NgForm } from '@angular/forms';
@Component({
selector: 'app-article-editor',
template: `
<form #f="ngForm" (ngSubmit)="saveArticle(f)">
<div ngModelGroup="article">
<p><input ngModel name="title" placeholder="Article title"></p>
<p><textarea ngModel name="text" placeholder="Article text"></textarea></p>
</div>
<p><button type="submit">Save</button></p>
</form>
`
})
export class ArticleEditorComponent {
saveArticle(f: NgForm): void {
console.log(f);
}
}
import { Component, Inject } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-article-editor',
template: `
<form [formGroup]="articleGroup" (ngSubmit)="saveArticle()">
<div formGroupName="article">
<p><input [formControl]="titleControl" placeholder="Article title"></p>
<p><textarea [formControl]="textControl" placeholder="Article text"></textarea></p>
</div>
<p><button type="submit">Save</button></p>
</form>
`
})
export class ArticleEditorComponent {
titleControl = new FormControl(null, Validators.required);
textControl = new FormControl(null, Validators.required);
articleGroup: FormGroup;
constructor(@Inject(FormBuilder) formBuilder: FormBuilder) {
this.articleGroup = formBuilder.group({
article: formBuilder.group({
title: this.titleControl,
text: this.textControl
})
});
}
saveArticle(): void {
console.log(this.articleGroup);
}
}
CustomValidator:
import { Component, Directive } from '@angular/core';
import { FormControl, Validator, NG_VALIDATORS } from '@angular/forms';
@Directive({
selector: '[appMaxWordCount]',
providers: [{
provide: NG_VALIDATORS,
useExisting: MaxWordCountValidatorDirective,
multi: true
}]
})
export class MaxWordCountValidatorDirective implements Validator {
validate(c: FormControl): {[key: string]: any} {
const wordCt: number = ((c.value || '').match(/\S+/g) || []).length;
return wordCt <= 10 ? null : {maxwords: {limit: 10, actual: wordCt}};
}
}
@Component({
selector: 'app-article-editor',
template: `
<h2>The Will to Win is nothing witout the Will to Prepare</h2>
<textarea [formControl]="bodyControl" required
appMaxWordCount placeholder="Article text"></textarea>
<p><button (click)="saveArticle()">Save</button></p>
`
})
export class ArticleEditorComponent {
articleBody = '';
bodyControl: FormControl = new FormControl();
saveArticle(): void {
if (this.bodyControl.valid) {
alert('Valid!');
} else {
alert('Invalid!');
}
}
}
Converting Observable to a Promise:
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-article',
template: `
<h2>The Will to Win is nothing witout the Will to Prepare</h2>
<div> {{ results | json }}</div>
`
})
export class ArticleEditorComponent {
results;
constructor(private http: HttpClient) {
http.get(`https://jsonplaceholder.typicode.com/posts`)
.toPromise().then(data => {
this.results = data;
});
}
}
Basic Observable:
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-article',
template: `
<h2>The Will to Win is nothing witout the Will to Prepare</h2>
<h1>{{ user }}</h1>
<p>{{ title }}</p>
`
})
export class ArticleEditorComponent {
user = '';
title = '';
constructor(private http: HttpClient) {
http.get(`https://jsonplaceholder.typicode.com/posts/1`)
.subscribe(data => {
this.user = data['userId'];
this.title = data['title'];
},
error => console.log(error));
}
Publish Subscribe Model:
import { Component } from '@angular/core';
import { Subject } from 'rxjs/Subject';
@Component({
selector: 'app-click-observer',
template: `
<button (click)="clickEmitter.next($event)">Emit event!</button>
<p *ngFor="let click of clicks; let i = index;">
{{ i }}: {{ click }}
</p>
`
})
export class ClickObserverComponent {
clickEmitter: Subject<Event> = new Subject();
clicks: Array<Event> = [];
constructor() {
this.clickEmitter.subscribe(clickEvent => this.clicks.push(clickEvent));
}
}
import { Component } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
@Component({
selector: 'app-click-observer',
template: `
<button (click)="publish($event)">Emit event!</button>
<p *ngFor="let click of clicks; let i = index;">
{{ i }}: {{ click }}
</p>
`
})
export class ClickObserverComponent {
clickEmitter: Observable<Event>;
private clickSubject_: Subject<Event> = new Subject();
clicks: Array<Event> = [];
constructor() {
this.clickEmitter = this.clickSubject_.asObservable();
this.clickEmitter.subscribe(clickEvent => this.clicks.push(clickEvent));
}
publish(e: Event): void {
this.clickSubject_.next(e);
}
}
import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/fromEvent';
@Component({
selector: 'app-click-observer',
template: `
<button #btn>Emit event!</button>
<p *ngFor="let click of clicks; let i = index;">
{{ i }}: {{ click }}
</p>
`
})
export class ClickObserverComponent implements AfterViewInit {
@ViewChild('btn') btn;
clickEmitter: Observable<Event>;
clicks: Array<Event> = [];
ngAfterViewInit() {
this.clickEmitter = Observable.fromEvent(this.btn.nativeElement, 'click');
this.clickEmitter.subscribe(clickEvent => this.clicks.push(clickEvent));
}
}
BehaviorSubject:
import { Component, Injectable, OnDestroy } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
@Injectable()
export class AuthService {
private authManager_: BehaviorSubject<AuthState> = new BehaviorSubject(AuthState.LoggedOut);
private authState_: AuthState;
authChange: Observable<AuthState>;
constructor() {
this.authChange = this.authManager_.asObservable();
}
login(): void {
this.setAuthState_(AuthState.LoggedIn);
}
logout(): void {
this.setAuthState_(AuthState.LoggedOut);
}
emitAuthState(): void {
this.authManager_.next(this.authState_);
}
private setAuthState_(newAuthState: AuthState): void {
this.authState_ = newAuthState;
this.emitAuthState();
}
}
export const enum AuthState {
LoggedIn,
LoggedOut
}
@Component({
selector: 'app-login',
template: `
<button *ngIf="!loggedIn" (click)="login()">
Login
</button>
<button *ngIf="loggedIn" (click)="logout()">
Logout
</button>
`
})
export class LoginComponent implements OnDestroy {
loggedIn = false;
private authChangeSubscription_: Subscription;
constructor(private authService_: AuthService) {
this.authChangeSubscription_ = authService_.authChange.subscribe(newAuthState => {
this.loggedIn = (newAuthState === AuthState.LoggedIn);
});
}
login(): void {
this.authService_.login();
}
logout(): void {
this.authService_.logout();
}
ngOnDestroy() {
this.authChangeSubscription_.unsubscribe();
}
}
Generalized Publish-Subscribe Service:
import { Component, Input, Injectable, AfterViewInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';
import { Subscription } from 'rxjs/Subscription';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';
@Injectable()
export class PubSubService {
private publishSubscribeSubject_: Subject<any> = new Subject();
emitter_: Observable<any>;
constructor() {
this.emitter_ = this.publishSubscribeSubject_.asObservable();
}
publish(channel: string, event: any): void {
this.publishSubscribeSubject_.next({
channel: channel,
event: event
});
}
subscribe(channel: string, handler: ((value: any) => void)): Subscription {
return this.emitter_
.filter(emission => emission.channel === channel)
.map(emission => emission.event)
.subscribe(handler);
}
}
export const enum AuthState {
LoggedIn,
LoggedOut
}
@Component({
selector: 'app-node',
template: `
<p>Heard {{ count }} of {{ subscribeChannel }}</p>
<button (click)="send()">Send {{ publishChannel }}</button>
`
})
export class NodeComponent implements AfterViewInit, OnDestroy {
@Input() publishChannel: string;
@Input() subscribeChannel: string;
count = 0;
private pubSubServiceSubscription_: Subscription;
constructor(private pubSubService_: PubSubService) { }
send() {
this.pubSubService_.publish(this.publishChannel, {});
}
ngAfterViewInit() {
this.pubSubServiceSubscription_ =
this.pubSubService_.subscribe(this.subscribeChannel, event => ++this.count);
}
ngOnDestroy() {
this.pubSubServiceSubscription_.unsubscribe();
}
}
QueryLists:
import { Component, Input, ViewChildren, AfterViewInit,
QueryList, ChangeDetectorRef } from '@angular/core';
@Component({
selector: 'app-inner',
template: `
<p>{{ val }}</p>
`
})
export class InnerComponent {
@Input() val: number;
}
@Component({
selector: 'app-outer',
template: `
<button (click)="add()">More</button>
<button (click)="remove()">Less</button>
<button (click)="shuffle()">Shuffle</button>
<app-inner
*ngFor="let i of list" val="{{ i }}">
</app-inner>
<p>Value of last: {{ lastVal }}</p>
`
})
export class OuterComponent implements AfterViewInit {
@ViewChildren(InnerComponent) innerComponents: QueryList<InnerComponent>;
list: Array<number> = [];
lastVal = 0;
constructor(private changeDetectorRef_: ChangeDetectorRef) { }
add(): void {
this.list.push(this.list.length);
}
remove(): void {
this.list.pop();
}
shuffle(): void {
this.list = this.list.sort(() => (4 * Math.random() > 2) ? 1 : -1);
}
ngAfterViewInit() {
this.innerComponents.changes.subscribe(innerComponents => {
this.lastVal = (innerComponents.last || {}).val;
this.changeDetectorRef_.detectChanges();
});
}
}
Autocomplete Observable:
import { Component, Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { FormControl } from '@angular/forms';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/concatMap';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/delay';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/switchMap';
@Injectable()
export class APIService {
constructor(private http: HttpClient) { }
search(query: string): Observable<string> {
return this.http.get('./assets/response.json')
.map(r => r['prefix'] + query)
.concatMap(x => Observable.of(x).delay(Math.random() * 1000));
}
}
@Component({
selector: 'app-search',
template: `
<input [formControl]="queryField">
<p *ngFor="let result of results">{{ result }}</p>
`
})
export class SearchComponent {
results: Array<string> = [];
queryField: FormControl = new FormControl();
constructor(private apiService_: APIService) {
this.queryField.valueChanges
.debounceTime(200)
.distinctUntilChanged()
.switchMap(query => this.apiService_.search(query))
.subscribe(result => this.results.push(result));
}
search(query: string): void {
this.apiService_.search(query).subscribe(result => this.results.push(result));
}
}