web-dev-qa-db-fra.com

Angular + Material - Comment gérer plusieurs cases à cocher avec formgroup

J'ai une liste d'intérêts que je reçois du backend. Je veux qu'un utilisateur puisse sélectionner les intérêts qu'il souhaite. Je ne stocke que les intérêts qu'ils ont vérifiés dans la base de données et je les préremplit lorsqu'ils chargent la page. Mais d'abord, je dois obtenir ces intérêts que l'utilisateur a sélectionnés.

interest.component.ts

export class InterestsComponent implements OnInit {

  interestFormGroup : FormGroup
  interests:any;
  selected: any;


  constructor(public interestService: InterestService, private formBuilder: FormBuilder,
  ) { }

  ngOnInit() {

    this.interestFormGroup = this.formBuilder.group({
      interests: this.formBuilder.array([])
    });


    this.interestService.all().subscribe((res) => {

      this.interests = res;

    });

  }

  change() {
    console.log(this.interestFormGroup.value);
  }

}

interest.component.html

<div id="interest">

    <div class="interest-list">

        <form [formGroup]="interestFormGroup">
            <div *ngFor="let interest of interests" >
                <mat-checkbox class="example-margin" formNameArray="interests" (change)="change()">{{interest}}</mat-checkbox>
            </div>
        </form>

    </div>

</div>

Dans mon console.log sur l'événement de modification, il indique qu'aucune valeur n'est ajoutée au tableau des intérêts dans le groupe interestFormGroup. Même si les cases à cocher sont cochées.

13
Kay

Vous devez ajouter des contrôles à FormArray manuellement comme:

this.interests = res;
const formArray = this.interestFormGroup.get('interests') as FormArray;
this.interests.forEach(x => formArray.Push(new FormControl(false)));

puis modifiez le modèle comme suit:

<form [formGroup]="interestFormGroup" (ngSubmit)="submit()">
   <ng-container formArrayName="interests">
      <div *ngFor="let interest of interests; let i = index" >
         <mat-checkbox class="example-margin" [formControlName]="i">
           {{interest}}
         </mat-checkbox>
      </div>
   </ng-container>
   <button>Submit</button>
</form>

Et lorsque vous soumettez un formulaire, vous devez transformer les valeurs de FormArray en votre résultat souhaité:

submit() {
  const result = Object.assign({}, 
    this.interestFormGroup.value, { 
      interests: this.interests
        .filter((x, i) => !!this.interestFormGroup.value.interests[i])});

  console.log(result);
}

La solution alternative est d'écouter l'événement change et d'ajouter et de supprimer manuellement la valeur de FormArray:

<div *ngFor="let interest of interests; let i = index" >
   <mat-checkbox class="example-margin" 
                (change)="onChange($event)" [value]="interest">{{interest}}</mat-checkbox>
</div>

onChange(event) {
  const interests = <FormArray>this.interestFormGroup.get('interests') as FormArray;

  if(event.checked) {
    interests.Push(new FormControl(event.source.value))
  } else {
    const i = interests.controls.findIndex(x => x.value === event.source.value);
    interests.removeAt(i);
  }
}

exemple Stackblitz

17
yurzui