I'm using Angular 17 with the following code:
database.component.html
@for(user of (users | userPipe:filters); track user.id) {
<tr id="{{ user.id }}">
<td>{{ user.name }}</td>
<td>{{ user.surname }}</td>
<td>{{ user.age }}</td>
</tr>
}
@empty {
<tr>
<td colspan="3">Empty</td>
</tr>
}
filters
is a string array with the keywords for filtering the matched database entries.
database.pipe.ts
@Pipe({
name: 'userPipe',
pure: false
})
export class databasePipe implements PipeTransform {
transform(values: Users[], filters: string[]): Users[] {
if (!filters || filters.length === 0 || values.length === 0) {
return values;
}
return values.filter((value: User) => {
filters.forEach(filter => {
const userNameFound = value.name.toLowerCase().indexOf(filter.toLowerCase()) !== -1;
const userSurnameFound = value.surname.toLowerCase().indexOf(filter.toLowerCase()) !== -1;
const ageFound = value.age.toLowerCase().indexOf(filter.toLowerCase()) !== -1;
if (userNameFound || userSurnameFound || ageFound) {
console.log("value: ", value);
return value;
}
return "";
});
});
}
}
It is working and I can see matching entries with value: <value>
in the browser console just fine but my filtered table just returns "Empty" and no data is shown.
Does anyone know why this happens?
Your filter logic in databasePipe
is incorrect. You are not returning the boolean value (predicate) to indicate that the element is selected, but return undefined
(falsy value). Thus, your table will show the @empty
template.
Instead, you should use .some()
so that it returns true
when fulfilling any filter
.
return values.filter((value: User) => {
return filters.some((filter) => {
const userNameFound =
value.name.toLowerCase().indexOf(filter.toLowerCase()) !== -1;
const userSurnameFound =
value.surname.toLowerCase().indexOf(filter.toLowerCase()) !== -1;
const ageFound =
value.age.toLowerCase().indexOf(filter.toLowerCase()) !== -1;
return userNameFound || userSurnameFound || ageFound;
});
});