#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
- Определите
datasource
какObservable
dataSource = [
{
firstname: "James",
lastname: "Amstrong",
othernames: "Angel",
age: 35
},
{
firstname: "John",
lastname: "Peter",
othernames: "Ava",
age: 43
},
...
]
Мы преобразуем это datasource
в наблюдаемое, используя of
from 'rxjs'
- Определите фильтр как
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: ''}, ...]>
- Объедините два и верните новое
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())
)
)
)
)
- Определите обработчик для
inputChange
public inputChange(event: any, key) {
this.filterKeyValues.find(({key: testKey}) => testKey === key).value = event.target.value
this.filterSubject$.next(this.filterKeyValues)
}
- Используется
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.