Search code examples
javascriptangularcheckboxangular2-forms

Angular ReactiveForms: Producing an array of checkbox values?


Given a list of checkboxes bound to the same formControlName, how can I produce an array of checkbox values bound to the formControl, rather than simply true/false?

Example:

<form [formGroup]="checkboxGroup">
    <input type="checkbox" id="checkbox-1" value="value-1" formControlName="myValues" />
    <input type="checkbox" id="checkbox-2" value="value-2" formControlName="myValues" />
    <input type="checkbox" id="checkbox-3" value="value-2" formControlName="myValues" />
</form>

checkboxGroup.controls['myValues'].value currently produces:

true or false

What I want it to produce:

['value-1', 'value-2', ...]

Solution

  • With the help of silentsod answer, I wrote a solution to get values instead of states in my formBuilder.

    I use a method to add or remove values in the formArray. It may be a bad approch, but it works !

    component.html

    <div *ngFor="let choice of checks; let i=index" class="col-md-2">
      <label>
        <input type="checkbox" [value]="choice.value" (change)="onCheckChange($event)">
        {{choice.description}}
      </label>
    </div>
    

    component.ts

    // For example, an array of choices
    public checks: Array<ChoiceClass> = [
      {description: 'descr1', value: 'value1'},
      {description: "descr2", value: 'value2'},
      {description: "descr3", value: 'value3'}
    ];
    
    initModelForm(): FormGroup{
      return this._fb.group({
        otherControls: [''],
        // The formArray, empty 
        myChoices: new FormArray([]),
      }
    }
    
    onCheckChange(event) {
      const formArray: FormArray = this.myForm.get('myChoices') as FormArray;
    
      /* Selected */
      if(event.target.checked){
        // Add a new control in the arrayForm
        formArray.push(new FormControl(event.target.value));
      }
      /* unselected */
      else{
        // find the unselected element
        let i: number = 0;
    
        formArray.controls.forEach((ctrl: FormControl) => {
          if(ctrl.value == event.target.value) {
            // Remove the unselected element from the arrayForm
            formArray.removeAt(i);
            return;
          }
    
          i++;
        });
      }
    }
    

    When I submit my form, for example my model looks like:

      otherControls : "foo",
      myChoices : ['value1', 'value2']
    

    Only one thing is missing, a function to fill the formArray if your model already has checked values.