1

I am building a new web application in Angular7.

I have a data table and I want to build server-side search functionality based on search values for each column. I have an input element at the top of each column in the data table. The search filtering should be triggered each time the search value changes in any of the input boxes.

I think I need to bind the keyup event to detect the change of value. I am using rxjs fromEvent and this does work, however, it detects the keyup of ANY keyboard event, not just the events tied to the relevant input boxes. I want to avoid unnecessary events since this will call the server-side filtering each time.

HTML

<table mat-table [dataSource]="data" class="example-table" matSort>
  <!-- ItemID Column -->
  <ng-container matColumnDef="ItemID">
    <th class="header" mat-header-cell *matHeaderCellDef>
      <div mat-sort-header>ItemID</div>
      <mat-form-field class="filter" floatLabel="never">
        <input
          matInput
          placeholder="Search ItemID"
          #input
          [(ngModel)]="searchValues.ItemID"
        >
      </mat-form-field>
    </th>
    <td mat-cell *matCellDef="let row">{{row.ItemID}}</td>
  </ng-container>

  <!-- IdentificationID Column -->
  <ng-container matColumnDef="IdentificationID">
    <th class="header" mat-header-cell *matHeaderCellDef>
      <div mat-sort-header>IdentificationID</div>
      <mat-form-field class="filter" floatLabel="never">
        <input
          matInput
          placeholder="Search IdentificationID"
          #input
          [(ngModel)]="searchValues.IdentificationID"
        >
      </mat-form-field>
    </th>
    <td mat-cell *matCellDef="let row">{{row.IdentificationID}}</td>
  </ng-container>
</table>

TS component

// TODO: bind to relevant input elements only
fromEvent<KeyboardEvent>(document, 'keyup')
  .pipe(
    debounceTime(150),
    distinctUntilChanged(),
    tap(() => {

      // call search function

    })
  )
  .subscribe();
pengz
  • 2,279
  • 3
  • 48
  • 91
  • 2
    You could handle `(ngModelChange)` with the same event handler for all input boxes, and use the technique mentioned in [this post](https://stackoverflow.com/q/41308826/1009922) to debounce the events. – ConnorsFan May 31 '19 at 20:32

1 Answers1

2

If you want to user fromEvent you can filter all events by tag name. In your case it will be like below:

// TODO: bind to relevant input elements only
fromEvent<KeyboardEvent>(document, 'keyup')
  .pipe(
    filter(e => e.target && e.target.tagName === 'INPUT') // filters only observables from INPUT
    debounceTime(150),
    distinctUntilChanged(),
    tap(() => {

      // call search function

    })
  )
  .subscribe();

Please pay attention on filter() operator which I added.

If you don't want to use fromEvent you can use angular built in bindings to bind input's keyup event:

<input (keyup)="searchTable($event)">

I prefer second option.

kat1330
  • 5,134
  • 7
  • 38
  • 61