I'm using a pipe so I can filter an array by a given property. Let's say it's an id.
<div #objs *ngFor="let obj of (arrayOfObj | pipe : search)">
...
</div>
I also added a ViewChildren to the element that contains the array.
@ViewChildren("objs") objs;
This is the input that controls the pipe:
<input type="text" [(ngModel)]="search" (ngModelChange)="inputSearch()">
This inputSearch()
function should simply control a number variable with the length of the filtered array every time the input value is changed:
inputSearch(){
this.lengthFilteredArray = this.objs.length;
console.log(this.objs);
}
Also, if I log objs
it contains a strange result, it kinda has two different lengths (I'd need the second result, the 0): log result
Here follows the transform()
of the pipe:
transform(array: Array<any>, search: string)
{
if (!array|| !search) {
return array;
}
return array.filter(o =>
o.name.toLowerCase().indexOf(search.toLowerCase()) !== -1);
}
With this approach, I'm getting like a "delayed" result. When I type a character, I receive the desired result only after I type the next character. Example: I type "x", the lengthFilteredArray
is 4, but the array is filtered to 0. If I erase the "x", lengthFilteredArray
is 0 and the array is not even filtered.
I don't know if this is best approach to this problem.
CodePudding user response:
The issue is you are checking length on ngModelChange
in "search
variable", by that time the this.objs
has not finished the processing or the pipe has not returned filter operated data.
You have to check result when the pipe has returned the filter data (you don't have a event for this here) or when the ngFor has finished processing the data (you have a event for this in this.objs.changes
)
export class AppComponent implements AfterViewInit {
@ViewChildren('objs') objs: QueryList<any>;
ngAfterViewInit(): void {
this.objs.changes.subscribe((obj) => this.log(obj));
}
log = (q) => console.log(q); // in your case check q.length here not on search change
}