I want when I type the name in the name input field to filter the FormArray data, and sort to what has been typed in the input box form FormArray data controls
<tbody formArrayName="cards">
<tr class="custom" *ngFor="let card of cardsArray().controls; index as i; " [formGroupName]="i">
<td class="pr-0">
<input [attr.id]="'name'+i" class="form-control form-control-sm" formControlName="name"
[readonly]="true">
</td>
</tr>
</tbody>
Observables to the rescue! :)
Attach a form control to your search field, listen to the changes of it and filter the values. Return an observable to the template and use the async pipe there. Here is a sample for you, you just need to change the variable names to fit your needs:
The input with the form control:
<input [formControl]="searchCtrl" placeholder="Search"/>
Let's say your form looks like this:
this.myForm = this.fb.group({
formArr: this.fb.array([
this.fb.group({
formCtrl: ['one']
}),
//... more
])
});
// just a getter for your formarray
get formArr() {
return (this.myForm.get('formArr') as FormArray).controls;
}
Then listen in the component for the change and do the above mentioned filter. I like to put a slight debounce time before making the filter, if the user types fast.
Then the filtered formArr$
variable (which is an observable):
formArr$ = this.searchCtrl.valueChanges.pipe(
startWith(''),
debounceTime(300),
switchMap((val: string) => {
return of(this.formArr as AbstractControl[]).pipe(
map((formArr: AbstractControl[]) =>
formArr.filter((group: AbstractControl) => {
return group.get('formCtrl').value
.toLowerCase()
.includes(val.toLowerCase());
})
)
);
})
);
Then just use the async
pipe in template:
<div *ngFor="let group of formArr$ | async">
<div formArrayName="formArr">
<div [formGroup]="group">
<input formControlName="formCtrl">
</div>
</div>
</div>
That's it! Here is a DEMO with the above code