web-dev-qa-db-fra.com

case à cocher mat angulaire dynamiquement avec ngModel

J'ai une offre de classe qui a une propriété "unités" comme tableau d'objets.

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

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

J'utilise Angular2, ces unités doivent être des cases à cocher que l'utilisateur peut sélectionner . J'utilise également un matériau angulaire.

Le code html ressemble à:

<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>    

La propriété des unités est chargée à l'aide de:

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));

Lorsque j'envoie le formulaire, la propriété cochée ne contient pas la valeur cochée.

Qu'est-ce que je fais mal??

6
aldo

Ajoutez [checked]="unit.checked" et supprimez ngModel, id et name de votre mat-checkbox. Cela crée une liaison dans un sens lorsque vous chargez la page, mais pour que la liaison dans les deux sens fonctionne, vous devez faire quelque chose de similaire, comme celui que j'ai déjà fait dans mon projet:

Passez le $event à la modification et définissez la valeur dans le fichier de composant manuellement:

Changez votre HTML en:

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

Ajoutez ceci au fichier de composant:

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

EDIT/UPDATE : Solution récemment trouvée pour une liaison bidirectionnelle sans la gérer explicitement

Assurez-vous que model.units possède une propriété pour checked. C'est le moyen le plus simple de l'ajouter: 

composant.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>

Si vous souhaitez contrôler les options d'activation/désactivation, essayez d'ajouter ceci:

composant.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>
7
Sri7

Ce travail pour moi a été testé dans Angular 7.

Juste pour vous assurer que ce nom est unique pour chaque case à cocher

<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>
1
San Jaisy

J'ai testé dans Angular 7 et je n'ai trouvé aucune erreur étant donné votre question. Vous pouvez voir une démo active dans cet exemple StackBlitz , mais ici va ma réponse.

Pour travailler, vous devez donner une name unique à votre entrée liée à ngModel.

Exemple en prenant votre code:

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

Je préfère ne pas utiliser la notation de tableau dans ces cas (units[{{i}}]), car cela signifie que tous les champs sont joints de la même façon, mais comme votre code semble fonctionner, il ne s'agit que d'une préférence et non de la cause de l'erreur.

0
Machado