Search code examples
angularbindingangular7mat-input

Angular mat-input bind [value] to [(ngModel)]


I have this table:

<table class="mat-elevation-z8">
          <tr *ngFor="let prescription of prescriptions" class="mat-row">
            <td>
              <mat-form-field class="">
                <input  [value]="prescription.description" matInput placeholder="Description">
              </mat-form-field>
            </td>
            <td>
              <mat-form-field class="">
                  <mat-select>
            <mat-option *ngFor="let object of selectedObjects" [value]="object.id" [(ngModel)]="prescription.idObject">
              {{object.description}}
            </mat-option>
          </mat-select>
        </mat-form-field>   
            </td>
            <td>
              <button mat-button class="delete" (click)="check(prescription)">delete</button>
            </td>
          </tr>
        </table>

where my array prescriptions has this structure:

 prescriptions = [
    {
      id: 1,
      description: "Prescrizione 1",
      date1: new Date(),
      date2: new Date(),
      idObject: 0
    },
    {
      id: 2,
      description: "Prescrizione 2",
      date1: new Date(),
      date2: new Date(),
      idObject: 0
    }
  ]

Each row of the table represents an object of this array. In each row there's a mat-select element that takes its options from this selectedObjects array:

"selectedObjects": [
        {
            "id":1, "description": "Desc1"
          },
          {
            "id":2, "description": "Desc2"
          },
          {
            "id":3, "descrizione": "Desc3"
          }

What I want to achieve is to bind the value of the selected option, that is object.id to the property idObject of the row element. So what I did was using [value]="object.id" [(ngModel)]="prescription.idObject" but it doesn't work, since the property remains 0 for all rows. I've checked this by printing the property in the method check (that is for each row).
Is there a way to implement this kind of binding?


Solution

  • You need to put the ngModel on the select not the option. It is your select that "changes" and is being set every time you choose an option not the option itself. Look at this example: https://stackblitz.com/angular/vkkalkxbmrok?file=app%2Fselect-form-example.ts

    EDIT: ok I got what you're trying to do here. You want to set the idObject inside each prescription. Binding the ngModel there on the select will copy over the whole selected object from selectedObjects and not just the ID:

    {"id":2, "description": "Desc2"}
    

    I'm not sure you can specify I just want a subobject of that select, but this is a perfect case where you can use:

    (selectionChange)="setPrescriptionId($event, prescription)"
    

    Angular 6 Material mat-select change method removed

    This will be invoked every time your selection changes.

    public setPrescriptionId(event: {id:string, description: string}, prescription: IYourPrescriptionInterface) {
        prescription.idObject = event.id;
    }