Фильтрация табличных данных для нескольких столбцов Angular 10

#javascript #angular #rxjs #angular10

#javascript #angular #rxjs #angular10

Вопрос:

Мне нужно отфильтровать данные таблицы в соответствии со значением, которое я установил при вводе keyup события. Поскольку существует несколько столбцов, отфильтрованные данные должны отображаться соответствующим образом.

В моем html у меня есть ниже

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

Мой файл TS выглядит следующим образом

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

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

     if (this.selectedId != '' amp;amp; 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] amp;amp; x[this.selectedId].toString().toLowerCase().includes(this.inputValue.toLowerCase()));
    this.result = filteredData;
    }
 

До сих пор я делал это и получал данные, отфильтрованные соответствующим образом, но когда я удаляю значение из определенного ввода фильтра, оно загружает источник данных.

Ожидается: для отображения ранее отфильтрованных данных вместо источника данных.

Комментарии:

1. Что вы подразумеваете под «удалением значения»? Сделать ввод пустым или нажать пробел?

2. Я сделал демо-версию stackblitz, не могли бы вы сказать, в чем проблема? stackblitz.com/edit /…

3. да @abney317 нажав пробел, он должен отображать ранее отфильтрованные данные

Ответ №1:

Для достижения этого я бы использовал следующие шаги, используя rxjs

  1. Определите datasource как Observable
 dataSource = [
    {
      firstname: "James",
      lastname: "Amstrong",
      othernames: "Angel",
      age: 35
    },
    {
      firstname: "John",
      lastname: "Peter",
      othernames: "Ava",
      age: 43
    },
...
]
 

Мы преобразуем это datasource в наблюдаемое, используя of from 'rxjs'

  1. Определите фильтр как Observable
    tableHeader = [
    {
      key: "firstname"
    },
    {
      key: "lastname"
    },
    ...
  ];
 filterKeyValues = this.tableHeader.map(({ key }) => ({ key, value: "" }));
 filterSubject$ = new BehaviorSubject(this.filterKeyValues)
  filter$ = this.filterSubject$.asObservable()
 

Это просто генерирует Observable со структурой

 Observable<[{ key: firtname, value: ''}, { key: lastname, value: ''}, ...]>
 
  1. Объедините два и верните новое Observable в качестве новых отфильтрованных данных
 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. Определите обработчик для inputChange
   public inputChange(event: any, key) {
    this.filterKeyValues.find(({key: testKey}) => testKey === key).value = event.target.value
    this.filterSubject$.next(this.filterKeyValues)
  }
 
  1. Используется async для отображения содержимого
 <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>
 

Мы вызываем следующее значение. это приведет к обнаружению изменений и datasorce$ Observable будет повторно оценено, что приведет к обновлению пользовательского интерфейса

Я сделал демонстрацию здесь, чтобы проиллюстрировать этот подход

Комментарии:

1. это именно то, чего я хотел, спасибо @Owen Kelvin.