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?
angular rxjs angular6 javascript-framework angular-pipe
add a comment |
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?
angular rxjs angular6 javascript-framework angular-pipe
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
add a comment |
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?
angular rxjs angular6 javascript-framework angular-pipe
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
angular rxjs angular6 javascript-framework angular-pipe
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
add a comment |
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
add a comment |
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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