Search code examples
angularformsangular-reactive-forms

Get values of checkboxes in angular reactive form


I have an angular reactive form for a survey. The ts file looks like this:

surveyForm = new FormGroup({
    question1: new FormControl(),
    question2: new FormControl(),
    question3: new FormControl(),
    question4: new FormControl(),
    question5: new FormControl(),
    question6: new FormControl(),
    question7: new FormControl(),
  })

onSubmit(){
    console.log(this.surveyForm.value);
  }

Then in my HTML in question 5 i have multiple checkboxes.

<p>
            <label for="question5"><b>What is your least favorite fruit </b></label>
            <br>
            <input type="checkbox" value="Apples" id="question5" name="question5" formControlName="question5"> Apples
            <br>
            <input type="checkbox" value="Bananas" id="question5" name="question5" formControlName="question5"> Bananas
            <br>
            <input type="checkbox" value="Pears" id="question5" name="question5" formControlName="question5"> Pears
            <br>
            <input type="checkbox" value="Pineapples" id="question5" name="question5" formControlName="question5"> Pineapples 
            <br>
            <input type="checkbox" value="Grapes" id="question5" name="question5" formControlName="question5"> Grapes  
            <br>
            <input type="checkbox" value="Musical Act" id="question5" name="question5" formControlName="question5"> Watermelon
            <br>
            <input type="checkbox" value="Other" id="question5" name="question5" formControlName="question5"> Other
        </p>

The problem is when I console log the survey value. In the questions that only use radio buttons or select options the data is given to me, however, when I have multiple checkboxes the data is only shown as true or false based on if anything was selected. How could I make the data show?


Solution

  • Binding several inputs to the same form control won't work. There is no easy way for directly receiving a list of the selected strings (like 'Apples', 'Bananas'). But for example you could use separate form controls for each fruit and then filter the form values by the boolean value.

    See an example implementation here:

    fruitsGroup = new FormGroup({
      apples: new FormControl(false),
      bananas: new FormControl(false),
    });
    
    getSelectedValues(): Array<string> {
      // Disclaimer: This code can be optimized
      const selectionMap: { [key: string]: boolean | null } =
        this.fruitsGroup.value;
      const selection: Array<string> = [];
    
      Object.keys(selectionMap).forEach((key) => {
        if (selectionMap[key]) {
          selection.push(key);
        }
      });
      return selection;
    }
    
    <form [formGroup]="fruitsGroup">
      <label><b>What is your least favorite fruit </b></label>
      <br />
      <input type="checkbox" formControlName="apples" /> Apples
      <br />
      <input type="checkbox" formControlName="bananas" /> Bananas
      <br />
    </form>
    
    {{ getSelectedValues() }}
    
    <!--
      Output, when both selected:
      apples, bananas
    -->
    
    

    Remarks:

    • Keep in mind that forms can be nested in Angular. So you can easily have a separate FormGroup for each question.
    • Based on your requirements, the code can be optimized of course. You could for example subscribe to formGroup.valueChanges.