typescript - angular mat-checkbox dynamiskt med ngModel


Jag har en klass Offer som har en egenskap "units" som en array av objekt.

export class Offer {
   public propertyA: string;
   public propertyB: string;
   public units: Unit[];
}

export class Unit {    
    public code: string,
    public name: string,
    public checked: boolean
}

Jag använder Angular2, dessa enheter måste vara kryssrutor som användaren kan välja. Jag använder även Angular Material.

HTML-koden ser ut så här:

<div *ngFor="let unit of model.units; let i=index">
  <mat-checkbox [(ngModel)]="model.units[i].checked"
    id="units[{{i}}]" name="units[{{i}}]">
       {{ unit.name }}
  </mat-checkbox>                        
</div>    

Egenskapen units läses in med:

this.model.units.push(new Unit("code1","name1", false));
this.model.units.push(new Unit("code2","name2", false));
this.model.units.push(new Unit("code3","name3", false));

När jag skickar formuläret innehåller inte den markerade egenskapen det markerade värdet.

Vad gör jag för fel??

Svar #1

Lägg till [checked]="unit.checked" och ta bort ngModel, id och name från din mat-checkbox. Detta gör en enkelriktad bindning när du laddar sidan men för att få tvåvägsbindning att fungera behöver du göra något liknande detta som jag har gjort i mitt projekt:

Skicka $event vid förändring och sätt värdet i komponentfilen manuellt:

Ändra din HTML till:

<div *ngFor="let unit of model.units">
  <mat-checkbox [checked]="unit.checked" 
  (change)="valueChange(model.units,unit,$event)">
       {{ unit.name }}
  </mat-checkbox>                        
</div>

Lägg till detta i komponentfilen:

valueChange(model.units, unit, $event) {
        //set the two-way binding here for the specific unit with the event
        model.units[unit].checked = $event.checked;
    }

REDIGERA/UPPDATERA: Hittade nyligen en lösning för tvåvägsbindning utan att hantera det uttryckligen

Se till att model.units har en egenskap för checked. Detta är det enklaste sättet att lägga till det:

komponent.ts:

this.model.units.forEach(item => {
                       item.checked = false; //change as per your requirement
                    });

html :

 <div *ngFor="let unit of model.units;let i=index">
    <mat-checkbox [(ngModel)]="unit.checked" [checked]="unit.checked"                                                                                    
    name="{{i}}-name">  //make sure name is unique for every item                             
    </mat-checkbox>
</div>

Om du vill kontrollera alternativ för att aktivera/inaktivera, försök också att lägga till detta:

komponent.ts:

this.model.units.forEach(item => {
                       item.checked = false;//change as per your requirement
                       item.disabled = true;//change as per your requirement
                        });

html :

<div *ngFor="let unit of model.units;leti=index">
        <mat-checkbox [(ngModel)]="unit.checked" [checked]="unit.checked"
         [disabled]="unit.disabled"                                                                                    
       name="{{i}}-name">//make sure name is unique for every item
        </mat-checkbox>
    </div>

Svar #2

Detta arbete för mig testades i Angular 7.

Bara för att säkerställa att namnet är unikt för varje kryssruta

<mat-grid-list cols="4" rowHeight="100px">
                    <mat-grid-tile *ngFor="let item of aspNetRolesClaims" [colspan]="1" [rowspan]="1">
                        <span>{{item.claimValue}}</span>
                        <mat-checkbox [(ngModel)]="item.claimValue" name="{{item.claimType}}">{{item.claimType}}</mat-checkbox>
                    </mat-grid-tile>
                </mat-grid-list>

Relaterade artiklar