Я пытаюсь использовать два разных фильтра для таблицы объектов.
Первый - это обычный фильтр на основе текста и ввода и работает как положено.
Второй, который я пытаюсь заставить работать, - это ряд флажков с надписью «Уровень 1», «Уровень 2» и т. Д. При установке флажка я хочу отфильтровать по столбцу «уровень» все проверенные в настоящий момент флажки. В идеале пользователь может фильтровать таблицу как по тексту, так и по уровню выбора
Я читал об использовании filterPredicate и пытался использовать в качестве шаблона , но я, должно быть, что-то упустил, любые указатели приветствуются.
Текущий фрагмент кода:
HTML:
//Input for text filter
<mat-form-field >
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter...">
</mat-form-field>
...
//Checkboxes for level filter
<div fxLayout="row" fxLayoutAlign="space-between center" class="margin-1">
<mat-checkbox (change)="customFilterPredicate()" [(ngModel)]="level.active" *ngFor="let level of levelsToShow">{{level.level}}</mat-checkbox>
</div>
TS
ngOnInit() {
this.dataSource.filterPredicate = this.customFilterPredicate();
}
...
applyFilter(filterValue: string) {
this.dataSource.filter = filterValue.trim().toLowerCase();
}
customFilterPredicate() {
const myFilterPredicate = (data): boolean => {
return this.levelsToShow.some(data['level'].toString().trim());
};
return myFilterPredicate;
}
Обновление
До сих пор мне удалось добиться некоторого прогресса благодаря Фабиану Кунгу, но я все еще не свободен дома. Чтобы уточнить, я надеюсь, что текстовый фильтр сможет выполнять поиск по нескольким столбцам («castingTime», «duration» и т. Д.), А флажки будут фильтроваться только по уровню (странные запросы, но я делаю это для друга так что я просто пытаюсь помочь ему).
На данный момент, когда я нажимаю на флажок, я получаю эту ошибку:
'Не удается прочитать свойство' toLowerCase 'из неопределенного'
которая указывает на эту строку кода:
return data['level'].toString().trim().toLowerCase().indexOf(searchString.name.toLowerCase()) !== -1 &&
но когда я утешаю данные для выхода из системы, я вижу, что они имеют свойство level, поэтому я не вижу, в чем я ошибаюсь.
Любая помощь приветствуется, спасибо!
Вот соответствующие фрагменты кода:
HTML:
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter..." [formControl]="textFilter">
<mat-checkbox (change)="updateFilter()" [(ngModel)]="level.active" *ngFor="let level of levelsToShow">{{level.name}}</mat-checkbox>
TS:
levelsToShow: Level[] = [
{ level: '1', active: false, name: 'Level 1' },
{ level: '2', active: false, name: 'Level 2' },
{ level: '3', active: false, name: 'Level 3' },
{ level: '4', active: false, name: 'Level 4' },
{ level: '5', active: false, name: 'Level 5' },
{ level: '6', active: false, name: 'Level 6' },
{ level: '7', active: false, name: 'Level 7' },
{ level: '8', active: false, name: 'Level 8' },
{ level: '9', active: false, name: 'Level 9' }
];
levelFilter = new FormControl();
textFilter = new FormControl();
globalFilter = '';
filteredValues = {
level: '',
text: '',
};
ngOnInit() {
...
this.textFilter.valueChanges.subscribe((textFilterValue) => {
this.filteredValues['text'] = textFilterValue;
this.dataSource.filter = JSON.stringify(this.filteredValues);
});
this.dataSource.filterPredicate = this.customFilterPredicate();
}
customFilterPredicate() {
const myFilterPredicate = (data: Spell, filter: string): boolean => {
var globalMatch = !this.globalFilter;
if (this.globalFilter) {
// search all text fields
globalMatch = data['spellName'].toString().trim().toLowerCase().indexOf(this.globalFilter.toLowerCase()) !== -1 ||
data['level'].toString().trim().toLowerCase().indexOf(this.globalFilter.toLowerCase()) !== -1 ||
data['castingTime'].toString().trim().toLowerCase().indexOf(this.globalFilter.toLowerCase()) !== -1 ||
data['distance'].toString().trim().toLowerCase().indexOf(this.globalFilter.toLowerCase()) !== -1 ||
data['details'].toString().trim().toLowerCase().indexOf(this.globalFilter.toLowerCase()) !== -1 ||
data['duration'].toString().trim().toLowerCase().indexOf(this.globalFilter.toLowerCase()) !== -1 ||
data['school'].toString().trim().toLowerCase().indexOf(this.globalFilter.toLowerCase()) !== -1 ||
data['effect'].toString().trim().toLowerCase().indexOf(this.globalFilter.toLowerCase()) !== -1;
}
if (!globalMatch) {
return;
}
let searchString = JSON.parse(filter);
return data['level'].toString().trim().toLowerCase().indexOf(searchString.name.toLowerCase()) !== -1 &&
(this.levelsToShow.filter(level => !level.active).length === this.levelsToShow.length ||
this.levelsToShow.filter(level => level.active).some(level => level.level === data.level.toString()));
}
return myFilterPredicate;
}
updateFilter() {
this.dataSource.filter = JSON.stringify(this.filteredValues);
}
Обновление II
В соответствии с запросом приведен пример одной из строк таблицы:
(на случай, если это поможет, для таблицы заклинаний Д и Д для друга)
{
castingTime: "1 half action"
distance: "Short range attack"
duration: "1 round per Casting Level"
effect: "Once per round, you may take a half action to launch an arrow of acid from your palm, generating a new Spellcasting result to see if you hit.Each arrow inflicts 1d6 acid damage.↵ "
index: 0
level: "4"
school: "Creation"
spellName: "ACID ARROW"
}
* Окончательное обновление *
Это то, с чем я столкнулся на случай, если кто-нибудь застрянет. Спасибо Фабиану Кунгу за все это! Единственное странное замечание - это то, что я использовал фактическое значение текстового ввода "textFilter", потому что строковое преобразование текста FilterValues и последующий их синтаксический анализ (фильтр принимает только строки, насколько я могу судить) продолжали давать мне сообщение "Ошибка JSON , неожиданное значение в 0 "сообщениях, и насколько я могу судить, это будет работать нормально, КРОМЕ теперь мне нужно выяснить, как регулировать фильтр.
Но это уже другой вопрос! Лол.
Спасибо!
customFilterPredicate() {
const myFilterPredicate = (data: Spell, filter: string): boolean => {
var globalMatch = !this.globalFilter;
if (this.globalFilter) {
// search all text fields
globalMatch = data['spellName'].toString().trim().toLowerCase().indexOf(this.globalFilter.toLowerCase()) !== -1 ||
data['level'].toString().trim().toLowerCase().indexOf(this.globalFilter.toLowerCase()) !== -1 ||
data['castingTime'].toString().trim().toLowerCase().indexOf(this.globalFilter.toLowerCase()) !== -1 ||
data['distance'].toString().trim().toLowerCase().indexOf(this.globalFilter.toLowerCase()) !== -1 ||
data['details'].toString().trim().toLowerCase().indexOf(this.globalFilter.toLowerCase()) !== -1 ||
data['duration'].toString().trim().toLowerCase().indexOf(this.globalFilter.toLowerCase()) !== -1 ||
data['school'].toString().trim().toLowerCase().indexOf(this.globalFilter.toLowerCase()) !== -1 ||
data['effect'].toString().trim().toLowerCase().indexOf(this.globalFilter.toLowerCase()) !== -1;
}
if (!globalMatch) {
return;
}
return data.spellName.toString().trim().toLowerCase().indexOf(this.textFilter.value) !== -1 &&
(this.levelsToShow.filter(level => !level.active).length === this.levelsToShow.length ||
this.levelsToShow.filter(level => level.active).some(level => level.level === data.level.toString()));
}
return myFilterPredicate;
}