问题
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