Home > Enterprise >  What makes this chip-list fail in my Angular 14 and Angular material app?
What makes this chip-list fail in my Angular 14 and Angular material app?

Time:02-03

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

  1. What causes this error?
  2. 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"
  • Related