angularangular-materialangular-ngmodelmd-chip

How to bind mat-chip to ngmodel in Angular 6 with Material


I have a form in a mat-dialog who displays multiple fields. Most of them are input and work perfectly, they are binded with [(ngModel)] as shown below, but I would like a field with mat-chips and autocomplete (like here). My problem is that I don't know how to bind the selected chips with [(ngModel)] get the data.

My HTML :

<form class="mat-dialog-content" (ngSubmit)="submit" #formControl="ngForm">
<div class="form">
  <mat-form-field color="accent">
    <input matInput #inputname class="form-control" placeholder="Nom du WOD" [(ngModel)]="data.name" name="name" maxlength="50" required >
    <mat-error *ngIf="formControl.invalid">{{getErrorMessage()}}</mat-error>
    <mat-hint align="end">{{inputname.value?.length || 0}}/50</mat-hint>
  </mat-form-field>
</div>

<div class="form">
  <mat-form-field color="accent">
    <input matInput placeholder="Notes du coach" [(ngModel)]="data.coachesNotes" name="coachesNotes">
  </mat-form-field>
</div>

<div class="form">
  <mat-form-field class="chip-list" aria-orientation="horizontal">
    <mat-chip-list #chipList [(ngModel)]="data.movementsIds" name="movementsIds">
      <mat-chip
        *ngFor="let mouv of mouvs"
        [selectable]="selectable"
        [removable]="removable"
        (removed)="remove(mouv)">
        {{mouv}}
        <mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
      </mat-chip>
      <input
        placeholder="Ajouter un mouvement..."
        #mouvInput
        [formControl]="mouvCtrl"
        [matAutocomplete]="auto"
        [matChipInputFor]="chipList"
        [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
        [matChipInputAddOnBlur]="addOnBlur"
        (matChipInputTokenEnd)="add($event)"
      />
    </mat-chip-list>
    <mat-autocomplete #auto="matAutocomplete" (optionSelected)="selectedChip($event)">
      <mat-option *ngFor="let mouv of filteredMouvs | async" [value]="mouv">
        {{ mouv }}
      </mat-option>
    </mat-autocomplete>
  </mat-form-field>
</div>

<div mat-dialog-actions>
  <button mat-button [type]="submit" [disabled]="!formControl.valid" [mat-dialog-close]="1" (click)="confirmAdd()">Ajouter</button>
  <button mat-button (click)="onNoClick()" tabindex="-1">Annuler</button>
</div></form>

My component :

public confirmAdd(): void {
  this.dataService.addWod(this.data);
}

View of my filled form

When I click on the "add" button my item is added with all of the others fields but the "movementsIds" field is null as we can see in the console.

Thanks you in advance for any help you can bring me.


Solution

  • For those who could have the same problem, I've found a solution.

    Instead of bind the chip list to my "data.movementsIds" with [(ngModel)] I just pass the "mouvs" array to my "confirmAdd" function and then set the data.movementsIds with this array like that :

    HTML :

      <mat-form-field class="chip-list" aria-orientation="horizontal">
        <mat-chip-list #chipList>
          <mat-chip
            *ngFor="let mouv of mouvs"
            [removable]="removable"
            (removed)="remove(mouv)">
            {{mouv}}
            <mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
          </mat-chip>
          <input
            placeholder="Ajouter un mouvement..."
            #mouvInput
            [formControl]="movementsIds"
            [matAutocomplete]="auto"
            [matChipInputFor]="chipList"
            [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
            [matChipInputAddOnBlur]="addOnBlur"
            (matChipInputTokenEnd)="add($event)"/>
        </mat-chip-list>
        <mat-autocomplete #auto="matAutocomplete" (optionSelected)="selectedChip($event)">
          <mat-option *ngFor="let mouv of filteredMouvs | async" [value]="mouv">
            {{ mouv }}
          </mat-option>
        </mat-autocomplete>
      </mat-form-field>
    

    Component :

    public confirmAdd(mouvs: Array<any>): void {
       this.data.movementsIds = JSON.stringify(mouvs);
       this.dataService.addWod(this.data);
    }