angulartypescriptformbuilder

How to Bind Selected Checkbox Values to Form Array Using FormBuilder in Angular


I have a list of checkboxes, and I'm using Angular's FormBuilder to manage my form. I'm trying to bind the selected checkbox values to a form control named itemIds in my form group.

      constructor(private formBuilder: UntypedFormBuilder
        ) {
      }
    serviceTaskForm = this.formBuilder.group({
    ....
     itemIds : ['']
    })
  onCheckboxChange($event: MatLegacyCheckboxChange) {

  }

InHTML i'm using

  <form>
.....
      <mat-form-field appearance="fill">
        <div class="demo-select-all-checkboxes" *ngFor="let task of tasks">
          <mat-checkbox
            (change)="onCheckboxChange($event)"
            [value]="task.itemId">
            {{ previousTask.itemId }} {{ previousTask.invoice}} 
          </mat-checkbox>
        </div>
      </mat-form-field>
    </form>

enter image description here

I want the itemIds form control to be an array containing all the selected checkbox values. How can I achieve this?


Solution

    1. Your itemIds control should be a form control with the array value.

    2. To initialize the itemIds form control, you should work with the setValue() or patchValue method and provide an array value.

    3. For working multiple checkboxes with form control, you should have the following implementation:

      • onCheckBoxChange method to toggle the selected checkbox value from the array by event (checked/unchecked).
      • isChecked method to check the itemId is checked.
    import {
      MatCheckboxModule,
      MatCheckboxChange,
    } from '@angular/material/checkbox';
    
    serviceTaskForm = this.formBuilder.group({
      itemIds: [[]],
    });
    
    ngOnInit() {
      this.itemIdFormControl.patchValue([1]);
    }
    
    onCheckboxChange($event: MatCheckboxChange, itemId: number) {
      let value: number[] = this.itemIdFormControl.value;
    
      if ($event.checked) value.push(itemId);
      else value.splice(value.indexOf(itemId), 1);
    
      this.itemIdFormControl.setValue(value, {
        emitEvent: false,
      });
    }
    
    isChecked(itemId: number) {
      return this.itemIdFormControl.value.indexOf(itemId) > -1;
    }
    
    get itemIdFormControl() {
      return this.serviceTaskForm.controls['itemIds'];
    }
    

    For your view:

    1. You can't implement the <mat-checkbox> in the <mat-form-field> element. Remove the <mat-form-field> element. Reference: Angular material Error when mat-checkbox is imported

    2. Implement the [checked] attribute instead of [value] attribute.

    <ng-container class="demo-select-all-checkboxes" *ngFor="let task of tasks">
      <mat-checkbox
        (change)="onCheckboxChange($event, task.itemId)"
        [checked]="isChecked(task.itemId)"
      >
        {{ task.itemId }} {{ task.invoice }}
      </mat-checkbox>
    </ng-container>
    

    Demo @ StackBlitz