I am working on a form in Angular 14.
I am trying to add a field with Angular Material cips.
In the component's Typescript file, I have:
constructor(private fb: FormBuilder,) { }
public visible: boolean = true;
public selectable: boolean = true;
public removable: boolean = true;
public addOnBlur: boolean = true;
public readonly separatorKeysCodes: number[] = [ENTER, COMMA];
public myForm: FormGroup = new FormGroup({
companyName: new FormControl('', Validators.required),
countryName: new FormControl('', Validators.required),
bussinessLines: new FormGroup({
bussinessLines: this.fb.array([], Validators.required)
}),
});
get bussinessLineControls(): FormArray {
return this.myForm.get('bussinessLines') as FormArray;
}
public add(event: MatChipInputEvent): void {
const input = event.input;
const value = event.value;
// Add our bussinessLine
if ((value || "").trim()) {
this.bussinessLineControls.push(this.fb.control(value));
}
// Reset the input value
if (input) {
input.value = "";
}
}
public remove(bussinessLine: string): void {
const index = this.bussinessLineControls.value.indexOf(bussinessLine);
if (index >= 0) {
this.bussinessLineControls.removeAt(index);
}
}
In the template:
<form [formGroup]="myForm" novalidate>
<mat-form-field appearance="outline" floatLabel="always" >
<mat-label>Bussiness lines:</mat-label>
<mat-chip-list #chipList aria-label="Delect business line" formArrayName="bussinessLines">
<mat-chip *ngFor="let bussinessLine of bussinessLineControls.value" [selectable]="selectable" [removable]="removable"
(removed)="remove(bussinessLine)">
{{bussinessLine}}
<mat-icon matChipRemove *ngIf="removable">Cancel</mat-icon>
</mat-chip>
<input placeholder="New business line..."
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="addOnBlur"
(matChipInputTokenEnd)="add($event)">
</mat-chip-list>
</mat-form-field>
</form>
The problem
For a reason I was unable to understand, the console throws the error:
Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables
It seem to happen here:
<input placeholder="New business line..."
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="addOnBlur"
(matChipInputTokenEnd)="add($event)">
Questions
- What causes this error?
- What is the most reliable way to fix it?
CodePudding user response:
The error is occurring because you are trying to iterate over an object (FormArray) instead of an array. The "FormArray" class doesn't implement the Iterable interface.
To fix it, you can use the .controls property of the FormArray, which returns an array of its controls. So, in your template, replace:
<mat-chip *ngFor="let bussinessLine of bussinessLineControls.value" [selectable]="selectable" [removable]="removable" (removed)="remove(bussinessLine)">
{{bussinessLine}}
<mat-icon matChipRemove *ngIf="removable">Cancel</mat-icon>
</mat-chip>
with:
<mat-chip *ngFor="let bussinessLine of bussinessLineControls.controls; let i = index" [selectable]="selectable" [removable]="removable" (removed)="remove(i)" >
{{bussinessLine.value}}
<mat-icon matChipRemove *ngIf="removable">Cancel</mat-icon>
</mat-chip>
and in your remove function, change it to:
public remove(index: number): void {
this.bussinessLineControls.removeAt(index);
}
CodePudding user response:
Well... It's written in black and white, or more like in red and red :) You're passing an object
into *ngFor directive somewhere. You haven't provided enough of your code to find a bug, at least I am not able to find one. Can you maybe prove a bigger chunk? At least that including <mat-chip-grid #chipList>
and mat-chip-row *ngFor="let var of list"
? Because the only iterable in your component is: separatorKeysCodes
and bussinessLineControls
getter.
If I were to shoot blindfolded I would assume that you've forgotten to put controls
property into your *ngFor
// This is you'r code for *ngFor <mat-chip-row>
*ngFor="let businessLineControl of bussinessLineControls"
// This is how it should have been
*ngFor="let businessLineControl of bussinessLineControls.controls"