2

I need to filter the table data according to the value I set in the input on keyup event. As there are multiple columns, filtered data should be displayed accordingly.

In my html I have below

             <tr>
             <td *ngFor="let t of tableHeader">
               <input type="text" [id]="t.key" (keyup)="inputChange($event)">
               </td>
            </tr>

My TS file is as below

    public inputChange(value) {
    var prevData = this.dataSource;

    if (this.selectedId == '') {
      prevData = this.result;
    }
    else if (this.selectedId != '' && this.selectedId != value.target.id) {
      prevData = this.result;
    }

     if (this.selectedId != '' && filterValue.target.value == '') {   
       this.result = prevData;
       return;
     }
   
    this.selectedId = value.target.id;
    this.inputValue = value.target.value;

    var filteredData = this.result.filter(x => x[this.selectedId] && x[this.selectedId].toString().toLowerCase().includes(this.inputValue.toLowerCase()));
    this.result = filteredData;
    }

So far I have done this and get data filtered accordingly, but when I remove a value from a particular filter input, it loads the data source.

Expected: to display the previously filtered data instead of the data source.

3
  • What do you mean by "remove a value?" Making the input blank or hitting backspace? Commented Nov 30, 2020 at 15:20
  • I have made a stackblitz demo, could you say what the issue is? stackblitz.com/edit/… Commented Nov 30, 2020 at 16:52
  • yes @abney317 by hitting backspace it should display previously filtered data Commented Dec 1, 2020 at 10:20

1 Answer 1

1

To achieve this I would use below steps using rxjs

  1. Define the datasource as an Observable
dataSource = [
    {
      firstname: "James",
      lastname: "Amstrong",
      othernames: "Angel",
      age: 35
    },
    {
      firstname: "John",
      lastname: "Peter",
      othernames: "Ava",
      age: 43
    },
...
]

We will convert this datasource to an observable using of from 'rxjs'

  1. Define the filter as an Observable
   tableHeader = [
    {
      key: "firstname"
    },
    {
      key: "lastname"
    },
    ...
  ];
 filterKeyValues = this.tableHeader.map(({ key }) => ({ key, value: "" }));
 filterSubject$ = new BehaviorSubject(this.filterKeyValues)
  filter$ = this.filterSubject$.asObservable()

This simply generates an Observable with the structure

Observable<[{ key: firtname, value: ''}, { key: lastname, value: ''}, ...]>
  1. Combine the two and return a new Observable as the new filtered data
dataSource$ = combineLatest([
    this.filter$, of(this.dataSource)
  ]).pipe(
    map(([filter, dataSource]) => 
     dataSource.filter(item => 
        filter.every((value) => 
          (new RegExp(String(value.value).toLowerCase())).test(String(item[value.key]).toLowerCase())
          
        )
      )
    )
  )
  1. Define handler for the inputChange
  public inputChange(event: any, key) {
    this.filterKeyValues.find(({key: testKey}) => testKey === key).value = event.target.value
    this.filterSubject$.next(this.filterKeyValues)
  }
  1. Use async to display the contents
<table>
    <tr>
        <td *ngFor="let t of tableHeader">
            <input type="text" [id]="t.key" (keyup)="inputChange($event, t.key)">
           </td>
    </tr>
  <tr *ngFor="let item of  dataSource$ | async">
    <td>{{ item.firstname }}</td>
    <td>{{ item.lastname }}</td>
    <td>{{ item.othernames }}</td>
    <td>{{ item.age }}</td>
  </tr>
</table>

We are calling the next value. this will force a change detection and datasorce$ Observable will be reevaluated causing an update in the UI

I have made a Demo Here to illustrate this approach

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.