How to have the `searchTerm` input field being observed for its value change?

ぃ、小莉子 提交于 2019-12-11 06:32:51

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!