问题
I have two observables that work fine:
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
ngOnInit() {
...
merge(this.sort.sortChange, this.paginator.page)
.pipe(
startWith({}),
switchMap(() => {
return this.getUsers(this.sort.active, this.sort.direction, this.paginator.pageIndex);
}),
map(userApi => {
This allows for the getUsers service method to be called when the sorting or the pagination is updated.
Now, I'd like to also have this service method being called when a search term is typed in:
@ViewChild(String) searchTerm: string;
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
ngOnInit() {
...
merge(this.searchTerm.length, this.sort.sortChange, this.paginator.page)
.pipe(
startWith({}),
switchMap(() => {
return this.getUsers(this.searchTerm, this.sort.active, this.sort.direction, this.paginator.pageIndex);
}),
map(userApi => {
With the following template markup:
<mat-form-field>
<input matInput #searchTerm (keyup)="search($event.target.value)" placeholder="User name" autocomplete="off">
</mat-form-field>
But the service method is then never called, not even at page load time.
My idea is to have the searchTerm an observable, and have this observable being observed by the merge method. This way I only have one method call to the getUsers service method.
I also tried this statement (without the .length) but it did not change anything:
merge(this.searchTerm, this.sort.sortChange, this.paginator.page)
UPDATE: I'm now trying something along this line:
@ViewChild('searchTerm') searchTerm: ElementRef;
merge(this.searchTerm.nativeElement.changes, this.sort.sortChange, this.paginator.page)
The search event handler does update fine the searchTerm member variable:
search(searchTerm: string) {
this.searchTerm.nativeElement.value = searchTerm.trim().toLowerCase();
if (this.paginator) {
this.paginator.firstPage();
}
}
I suppose I can get the value of the input field element to call the service method:
return this.getUsers(this.searchTerm.nativeElement.value, this.sort.active, this.sort.direction, this.paginator.pageIndex);
But the merge is not fireing if it includes the this.searchTerm.nativeElement.changes as in:
merge(this.searchTerm.nativeElement.changes, this.sort.sortChange, this.paginator.page)
How to have the searchTerm input field being observed for its value change ?
回答1:
I finally could solve the issue, using an EventEmitter object:
@Input() searchTerm: string;
@Output() searchTermEvent = new EventEmitter<{ value: string }>();
merge(this.searchTermEvent, this.sort.sortChange, this.paginator.page)
.pipe(
startWith({}),
switchMap(() => {
this.isLoadingResults = true;
return this.getUsers(this.searchTerm, this.sort.active, this.sort.direction, this.paginator.pageIndex);
}),
The event is emitted with the handler:
search(searchTerm: string) {
this.searchTerm = searchTerm;
this.searchTermEvent.emit({
value: this.searchTerm
});
if (this.paginator) {
this.paginator.firstPage();
}
}
The getUsers service method is fired up on each input character.
Maybe there is a better alternative, but this works fine for now.
来源:https://stackoverflow.com/questions/52916861/how-to-have-the-searchterm-input-field-being-observed-for-its-value-change