How is it working this Angular pipe used to perform a dynamic search of terms inserted into an input tag in...











up vote
0
down vote

favorite












I am very new in Angualar and I am following this official Angular tutorial: https://angular.io/tutorial/toh-pt6



and I have some doubts about how it works, this is my commented code of the HeroSearchComponent class:



import { Component, OnInit } from '@angular/core';

import { Observable, Subject } from 'rxjs';

import {
debounceTime, distinctUntilChanged, switchMap
} from 'rxjs/operators';

import { Hero } from '../hero';
import { HeroService } from '../hero.service';

@Component({
selector: 'app-hero-search',
templateUrl: './hero-search.component.html',
styleUrls: [ './hero-search.component.css' ]
})
export class HeroSearchComponent implements OnInit {

// It is an Observable emitting an array of Hero objects:
heroes$: Observable<Hero>;

/**
* The searchTerms property is declared as an RxJS Subject.
* A Subject is both a source of observable values and an Observable itself.
* You can subscribe to a Subject as you would any Observable.
* You can also push values into that Observable by calling its next(value) method as the search() method does.
*/
private searchTerms = new Subject<string>();

constructor(private heroService: HeroService) {}

/**
* Push a search term into the observable stream.
* Every time the user types in the textbox, the binding calls search() with the textbox value, a "search term".
* The searchTerms becomes an Observable emitting a steady stream of search terms.
*/
search(term: string): void {
this.searchTerms.next(term);
}

ngOnInit(): void {
this.heroes$ = this.searchTerms.pipe(
// wait 300ms after each keystroke before considering the term
debounceTime(300),

// ignore new term if same as previous term
distinctUntilChanged(),

// switch to new search observable each time the term changes
switchMap((term: string) => this.heroService.searchHeroes(term)),
);
}
}


This class is used to search the heros from the hero-search.component.html containing:



<div id="search-component">
<h4>Hero Search</h4>

<!--
As the user types in the search box, a keyup event binding calls
the component's search() method with the new search box value
-->
<input #searchBox id="search-box" (keyup)="search(searchBox.value)" />

<ul class="search-result">
<!--
The *ngFor iterates over a list called heroes$, not heroes.
The $ is a convention that indicates heroes$ is an Observable, not an array.
The *ngFor can't do anything with an Observable.
But there's also a pipe character (|) followed by async, which identifies Angular's AsyncPipe.
The AsyncPipe subscribes to an Observable automatically so you
won't have to do so in the component class.
-->
<li *ngFor="let hero of heroes$ | async" >
<a routerLink="/detail/{{hero.id}}">
{{hero.name}}
</a>
</li>
</ul>
</div>


Here my interpretation, I am absolutly not sure if it is correct or not.



The heroes$ field of the HeroSearchComponent is not an array but it is an Observable emitting an array. This because we live in an asyncronous world so we have to wait that the server provide the response.



In the view I can't directly iterate on an array but I have to wait that I receive the response (when the previous Observable emit the array of Hero), this is done using the asyncornous pipe to register on this event:



<li *ngFor="let hero of heroes$ | async" >


This should be correct...



Then into the view I have:



<input #searchBox id="search-box" (keyup)="search(searchBox.value)" />


When the user insert a new character into the input tag it is called the component search() method passing the value inserted into the input tag ("a", "ab", "abc", "ab", etcetc).



This is the search() method:



search(term: string): void {
this.searchTerms.next(term);
}


Looking at it is not directly performing a search calling a backend service but it is pushing the received new term into the searchTerms.



This searchTerms object is a Subject. From what I have understood a Subject is an object that can emit event (as an Observable**) and at the same time can receive a stream of evens (in this case a stream of terms eacht time that the user insert a new char into the view search input).



But...how and where it is performed the call to obtain the heroes list matching with the inserted term?



My idea is the following one: it is not directly do in this method but there is something like a pre-setted behavior. This is done when this class is instanced by the ngOnInit() method:



ngOnInit(): void {
this.heroes$ = this.searchTerms.pipe(
// wait 300ms after each keystroke before considering the term
debounceTime(300),

// ignore new term if same as previous term
distinctUntilChanged(),

// switch to new search observable each time the term changes
switchMap((term: string) => this.heroService.searchHeroes(term)),
);
}


That basically says something like: call the heroService.searchHeroes(term) method (the method that perform the search on my backend) passing the term each time that the searchTerms receiveemit an event (that is the last term to search). In theory this pipe is setted to do it not for every char inserted but every 300ms to avoid to perform much call).



I am not sure about this mechanism and how exactly this pipe works.



What is the correct and complete interpretation?










share|improve this question




















  • 2




    So far all your interpretations are correct. The mentioned pipe (| async) makes an subscription to the given observable and returns the given value from the observable. Another possibility (or better what the async pipe does under the hood) is calling the subscribe method of the observable. The differences between both approaches can be read here. If you need more informations about the subscription itself take a look here
    – Oliver
    Nov 8 at 11:35















up vote
0
down vote

favorite












I am very new in Angualar and I am following this official Angular tutorial: https://angular.io/tutorial/toh-pt6



and I have some doubts about how it works, this is my commented code of the HeroSearchComponent class:



import { Component, OnInit } from '@angular/core';

import { Observable, Subject } from 'rxjs';

import {
debounceTime, distinctUntilChanged, switchMap
} from 'rxjs/operators';

import { Hero } from '../hero';
import { HeroService } from '../hero.service';

@Component({
selector: 'app-hero-search',
templateUrl: './hero-search.component.html',
styleUrls: [ './hero-search.component.css' ]
})
export class HeroSearchComponent implements OnInit {

// It is an Observable emitting an array of Hero objects:
heroes$: Observable<Hero>;

/**
* The searchTerms property is declared as an RxJS Subject.
* A Subject is both a source of observable values and an Observable itself.
* You can subscribe to a Subject as you would any Observable.
* You can also push values into that Observable by calling its next(value) method as the search() method does.
*/
private searchTerms = new Subject<string>();

constructor(private heroService: HeroService) {}

/**
* Push a search term into the observable stream.
* Every time the user types in the textbox, the binding calls search() with the textbox value, a "search term".
* The searchTerms becomes an Observable emitting a steady stream of search terms.
*/
search(term: string): void {
this.searchTerms.next(term);
}

ngOnInit(): void {
this.heroes$ = this.searchTerms.pipe(
// wait 300ms after each keystroke before considering the term
debounceTime(300),

// ignore new term if same as previous term
distinctUntilChanged(),

// switch to new search observable each time the term changes
switchMap((term: string) => this.heroService.searchHeroes(term)),
);
}
}


This class is used to search the heros from the hero-search.component.html containing:



<div id="search-component">
<h4>Hero Search</h4>

<!--
As the user types in the search box, a keyup event binding calls
the component's search() method with the new search box value
-->
<input #searchBox id="search-box" (keyup)="search(searchBox.value)" />

<ul class="search-result">
<!--
The *ngFor iterates over a list called heroes$, not heroes.
The $ is a convention that indicates heroes$ is an Observable, not an array.
The *ngFor can't do anything with an Observable.
But there's also a pipe character (|) followed by async, which identifies Angular's AsyncPipe.
The AsyncPipe subscribes to an Observable automatically so you
won't have to do so in the component class.
-->
<li *ngFor="let hero of heroes$ | async" >
<a routerLink="/detail/{{hero.id}}">
{{hero.name}}
</a>
</li>
</ul>
</div>


Here my interpretation, I am absolutly not sure if it is correct or not.



The heroes$ field of the HeroSearchComponent is not an array but it is an Observable emitting an array. This because we live in an asyncronous world so we have to wait that the server provide the response.



In the view I can't directly iterate on an array but I have to wait that I receive the response (when the previous Observable emit the array of Hero), this is done using the asyncornous pipe to register on this event:



<li *ngFor="let hero of heroes$ | async" >


This should be correct...



Then into the view I have:



<input #searchBox id="search-box" (keyup)="search(searchBox.value)" />


When the user insert a new character into the input tag it is called the component search() method passing the value inserted into the input tag ("a", "ab", "abc", "ab", etcetc).



This is the search() method:



search(term: string): void {
this.searchTerms.next(term);
}


Looking at it is not directly performing a search calling a backend service but it is pushing the received new term into the searchTerms.



This searchTerms object is a Subject. From what I have understood a Subject is an object that can emit event (as an Observable**) and at the same time can receive a stream of evens (in this case a stream of terms eacht time that the user insert a new char into the view search input).



But...how and where it is performed the call to obtain the heroes list matching with the inserted term?



My idea is the following one: it is not directly do in this method but there is something like a pre-setted behavior. This is done when this class is instanced by the ngOnInit() method:



ngOnInit(): void {
this.heroes$ = this.searchTerms.pipe(
// wait 300ms after each keystroke before considering the term
debounceTime(300),

// ignore new term if same as previous term
distinctUntilChanged(),

// switch to new search observable each time the term changes
switchMap((term: string) => this.heroService.searchHeroes(term)),
);
}


That basically says something like: call the heroService.searchHeroes(term) method (the method that perform the search on my backend) passing the term each time that the searchTerms receiveemit an event (that is the last term to search). In theory this pipe is setted to do it not for every char inserted but every 300ms to avoid to perform much call).



I am not sure about this mechanism and how exactly this pipe works.



What is the correct and complete interpretation?










share|improve this question




















  • 2




    So far all your interpretations are correct. The mentioned pipe (| async) makes an subscription to the given observable and returns the given value from the observable. Another possibility (or better what the async pipe does under the hood) is calling the subscribe method of the observable. The differences between both approaches can be read here. If you need more informations about the subscription itself take a look here
    – Oliver
    Nov 8 at 11:35













up vote
0
down vote

favorite









up vote
0
down vote

favorite











I am very new in Angualar and I am following this official Angular tutorial: https://angular.io/tutorial/toh-pt6



and I have some doubts about how it works, this is my commented code of the HeroSearchComponent class:



import { Component, OnInit } from '@angular/core';

import { Observable, Subject } from 'rxjs';

import {
debounceTime, distinctUntilChanged, switchMap
} from 'rxjs/operators';

import { Hero } from '../hero';
import { HeroService } from '../hero.service';

@Component({
selector: 'app-hero-search',
templateUrl: './hero-search.component.html',
styleUrls: [ './hero-search.component.css' ]
})
export class HeroSearchComponent implements OnInit {

// It is an Observable emitting an array of Hero objects:
heroes$: Observable<Hero>;

/**
* The searchTerms property is declared as an RxJS Subject.
* A Subject is both a source of observable values and an Observable itself.
* You can subscribe to a Subject as you would any Observable.
* You can also push values into that Observable by calling its next(value) method as the search() method does.
*/
private searchTerms = new Subject<string>();

constructor(private heroService: HeroService) {}

/**
* Push a search term into the observable stream.
* Every time the user types in the textbox, the binding calls search() with the textbox value, a "search term".
* The searchTerms becomes an Observable emitting a steady stream of search terms.
*/
search(term: string): void {
this.searchTerms.next(term);
}

ngOnInit(): void {
this.heroes$ = this.searchTerms.pipe(
// wait 300ms after each keystroke before considering the term
debounceTime(300),

// ignore new term if same as previous term
distinctUntilChanged(),

// switch to new search observable each time the term changes
switchMap((term: string) => this.heroService.searchHeroes(term)),
);
}
}


This class is used to search the heros from the hero-search.component.html containing:



<div id="search-component">
<h4>Hero Search</h4>

<!--
As the user types in the search box, a keyup event binding calls
the component's search() method with the new search box value
-->
<input #searchBox id="search-box" (keyup)="search(searchBox.value)" />

<ul class="search-result">
<!--
The *ngFor iterates over a list called heroes$, not heroes.
The $ is a convention that indicates heroes$ is an Observable, not an array.
The *ngFor can't do anything with an Observable.
But there's also a pipe character (|) followed by async, which identifies Angular's AsyncPipe.
The AsyncPipe subscribes to an Observable automatically so you
won't have to do so in the component class.
-->
<li *ngFor="let hero of heroes$ | async" >
<a routerLink="/detail/{{hero.id}}">
{{hero.name}}
</a>
</li>
</ul>
</div>


Here my interpretation, I am absolutly not sure if it is correct or not.



The heroes$ field of the HeroSearchComponent is not an array but it is an Observable emitting an array. This because we live in an asyncronous world so we have to wait that the server provide the response.



In the view I can't directly iterate on an array but I have to wait that I receive the response (when the previous Observable emit the array of Hero), this is done using the asyncornous pipe to register on this event:



<li *ngFor="let hero of heroes$ | async" >


This should be correct...



Then into the view I have:



<input #searchBox id="search-box" (keyup)="search(searchBox.value)" />


When the user insert a new character into the input tag it is called the component search() method passing the value inserted into the input tag ("a", "ab", "abc", "ab", etcetc).



This is the search() method:



search(term: string): void {
this.searchTerms.next(term);
}


Looking at it is not directly performing a search calling a backend service but it is pushing the received new term into the searchTerms.



This searchTerms object is a Subject. From what I have understood a Subject is an object that can emit event (as an Observable**) and at the same time can receive a stream of evens (in this case a stream of terms eacht time that the user insert a new char into the view search input).



But...how and where it is performed the call to obtain the heroes list matching with the inserted term?



My idea is the following one: it is not directly do in this method but there is something like a pre-setted behavior. This is done when this class is instanced by the ngOnInit() method:



ngOnInit(): void {
this.heroes$ = this.searchTerms.pipe(
// wait 300ms after each keystroke before considering the term
debounceTime(300),

// ignore new term if same as previous term
distinctUntilChanged(),

// switch to new search observable each time the term changes
switchMap((term: string) => this.heroService.searchHeroes(term)),
);
}


That basically says something like: call the heroService.searchHeroes(term) method (the method that perform the search on my backend) passing the term each time that the searchTerms receiveemit an event (that is the last term to search). In theory this pipe is setted to do it not for every char inserted but every 300ms to avoid to perform much call).



I am not sure about this mechanism and how exactly this pipe works.



What is the correct and complete interpretation?










share|improve this question















I am very new in Angualar and I am following this official Angular tutorial: https://angular.io/tutorial/toh-pt6



and I have some doubts about how it works, this is my commented code of the HeroSearchComponent class:



import { Component, OnInit } from '@angular/core';

import { Observable, Subject } from 'rxjs';

import {
debounceTime, distinctUntilChanged, switchMap
} from 'rxjs/operators';

import { Hero } from '../hero';
import { HeroService } from '../hero.service';

@Component({
selector: 'app-hero-search',
templateUrl: './hero-search.component.html',
styleUrls: [ './hero-search.component.css' ]
})
export class HeroSearchComponent implements OnInit {

// It is an Observable emitting an array of Hero objects:
heroes$: Observable<Hero>;

/**
* The searchTerms property is declared as an RxJS Subject.
* A Subject is both a source of observable values and an Observable itself.
* You can subscribe to a Subject as you would any Observable.
* You can also push values into that Observable by calling its next(value) method as the search() method does.
*/
private searchTerms = new Subject<string>();

constructor(private heroService: HeroService) {}

/**
* Push a search term into the observable stream.
* Every time the user types in the textbox, the binding calls search() with the textbox value, a "search term".
* The searchTerms becomes an Observable emitting a steady stream of search terms.
*/
search(term: string): void {
this.searchTerms.next(term);
}

ngOnInit(): void {
this.heroes$ = this.searchTerms.pipe(
// wait 300ms after each keystroke before considering the term
debounceTime(300),

// ignore new term if same as previous term
distinctUntilChanged(),

// switch to new search observable each time the term changes
switchMap((term: string) => this.heroService.searchHeroes(term)),
);
}
}


This class is used to search the heros from the hero-search.component.html containing:



<div id="search-component">
<h4>Hero Search</h4>

<!--
As the user types in the search box, a keyup event binding calls
the component's search() method with the new search box value
-->
<input #searchBox id="search-box" (keyup)="search(searchBox.value)" />

<ul class="search-result">
<!--
The *ngFor iterates over a list called heroes$, not heroes.
The $ is a convention that indicates heroes$ is an Observable, not an array.
The *ngFor can't do anything with an Observable.
But there's also a pipe character (|) followed by async, which identifies Angular's AsyncPipe.
The AsyncPipe subscribes to an Observable automatically so you
won't have to do so in the component class.
-->
<li *ngFor="let hero of heroes$ | async" >
<a routerLink="/detail/{{hero.id}}">
{{hero.name}}
</a>
</li>
</ul>
</div>


Here my interpretation, I am absolutly not sure if it is correct or not.



The heroes$ field of the HeroSearchComponent is not an array but it is an Observable emitting an array. This because we live in an asyncronous world so we have to wait that the server provide the response.



In the view I can't directly iterate on an array but I have to wait that I receive the response (when the previous Observable emit the array of Hero), this is done using the asyncornous pipe to register on this event:



<li *ngFor="let hero of heroes$ | async" >


This should be correct...



Then into the view I have:



<input #searchBox id="search-box" (keyup)="search(searchBox.value)" />


When the user insert a new character into the input tag it is called the component search() method passing the value inserted into the input tag ("a", "ab", "abc", "ab", etcetc).



This is the search() method:



search(term: string): void {
this.searchTerms.next(term);
}


Looking at it is not directly performing a search calling a backend service but it is pushing the received new term into the searchTerms.



This searchTerms object is a Subject. From what I have understood a Subject is an object that can emit event (as an Observable**) and at the same time can receive a stream of evens (in this case a stream of terms eacht time that the user insert a new char into the view search input).



But...how and where it is performed the call to obtain the heroes list matching with the inserted term?



My idea is the following one: it is not directly do in this method but there is something like a pre-setted behavior. This is done when this class is instanced by the ngOnInit() method:



ngOnInit(): void {
this.heroes$ = this.searchTerms.pipe(
// wait 300ms after each keystroke before considering the term
debounceTime(300),

// ignore new term if same as previous term
distinctUntilChanged(),

// switch to new search observable each time the term changes
switchMap((term: string) => this.heroService.searchHeroes(term)),
);
}


That basically says something like: call the heroService.searchHeroes(term) method (the method that perform the search on my backend) passing the term each time that the searchTerms receiveemit an event (that is the last term to search). In theory this pipe is setted to do it not for every char inserted but every 300ms to avoid to perform much call).



I am not sure about this mechanism and how exactly this pipe works.



What is the correct and complete interpretation?







angular rxjs angular6 javascript-framework angular-pipe






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 8 at 11:23









Oliver

31.9k767114




31.9k767114










asked Nov 8 at 11:14









AndreaNobili

12.9k53178315




12.9k53178315








  • 2




    So far all your interpretations are correct. The mentioned pipe (| async) makes an subscription to the given observable and returns the given value from the observable. Another possibility (or better what the async pipe does under the hood) is calling the subscribe method of the observable. The differences between both approaches can be read here. If you need more informations about the subscription itself take a look here
    – Oliver
    Nov 8 at 11:35














  • 2




    So far all your interpretations are correct. The mentioned pipe (| async) makes an subscription to the given observable and returns the given value from the observable. Another possibility (or better what the async pipe does under the hood) is calling the subscribe method of the observable. The differences between both approaches can be read here. If you need more informations about the subscription itself take a look here
    – Oliver
    Nov 8 at 11:35








2




2




So far all your interpretations are correct. The mentioned pipe (| async) makes an subscription to the given observable and returns the given value from the observable. Another possibility (or better what the async pipe does under the hood) is calling the subscribe method of the observable. The differences between both approaches can be read here. If you need more informations about the subscription itself take a look here
– Oliver
Nov 8 at 11:35




So far all your interpretations are correct. The mentioned pipe (| async) makes an subscription to the given observable and returns the given value from the observable. Another possibility (or better what the async pipe does under the hood) is calling the subscribe method of the observable. The differences between both approaches can be read here. If you need more informations about the subscription itself take a look here
– Oliver
Nov 8 at 11:35

















active

oldest

votes











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53206611%2fhow-is-it-working-this-angular-pipe-used-to-perform-a-dynamic-search-of-terms-in%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown






























active

oldest

votes













active

oldest

votes









active

oldest

votes






active

oldest

votes
















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53206611%2fhow-is-it-working-this-angular-pipe-used-to-perform-a-dynamic-search-of-terms-in%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Schultheiß

Verwaltungsgliederung Dänemarks

Liste der Kulturdenkmale in Wilsdruff