Introduction

Collecting user input on a website is definitely not something rare, and using checkboxes is probably the most common way to handle a situation where you want a user to make a selection on some data, in for example a list. There is a lot of ways to do this, some better than others, I recently had to implement this myself and thought I’d share my way of doing it. In this simplified tutorial we will create an array of dummy data that we use for our checkboxes, implement the template for our form and create a checkbox that allows the user to check or uncheck all of the boxes.
View demo.

Before we begin

If you are unfamiliar with forms in Angular, there are multiple ways to deal with them, one other being for example Template-driven Forms. I recommend that you read up on forms over at Angular’s own documentation to grasp the differences.

Setting up the checkbox list data

In this example we will pretend that the requested user input is the users favorite music genre. The dummy-data is pretty simple but enough for this example. Realistically, the data would probably come from some external resource via an API call or similar, and we would dynamically set up checkboxes for each item.


Creating the form functionality

After having the data in place, we start off by importing FormBuilder, FormGroup, FormArray, FormControl from @angular/forms. We proceed with declaring a FormGroup called musicForm in our component, that later gets created with the help of the FormGroup service, this provides us with the ability to communicate between the template code and TypeScript code in our component. In the constructor, we also create an array of FormControls, one for each object in the musicPreferences array, which means one for each single checkbox. The FormControls get initialized as false, meaning they are unchecked. We then proceed with passing the FormControls array into the constructor of FormArray in the FormGroup. Finally we add a submit() function, leaving it empty for now.


Creating the form HTML

The template for our component is nothing out of the ordinary, but there’s a few key points. With [formGroup]="musicForm" we bind the form element to our components form. The (ngSubmit)="submit()" basically binds the submit event of the form to the submit() function in our component. With the help of the *ngFor directive we iterate through all of our controls and create a label and checkbox for each. We simply specify the formControlName as the index of our iteration and we tell the Forms API that we belong to the FormArray by defining [formArrayName]="musicPreferences".

The submit function

In this example the submit function does not have any real purpose, but if we would like to get the checked values in our form after the user has clicked on the submit button, we could do so by implementing the following.

Implementing the select/unselect all checkbox

To preserve readability some lines of code have been omitted from the following gist, the final version including all code is available further down.

We start off by importing and implementing OnInit from @angular/core. Secondly we create a new FormControl in the constructor of our component called selectAllControl, and add it to the existing FormGroup called musicForm. In the ngOnInit function we call a new function called onChanges(), which sets up subscriptions for value changes on our form. The first subscription checks for changes on the selectAll checkbox and simply updates all of the individual checkboxes accordingly. Beware when using Array.fill with anything other than primitive datatypes as each row will only be a reference to the same object. The second subscription checks for changes on our musicPreferences checkboxes, and updates the selectAll checkbox to always properly match the selections that have been made. Take note of the { emitEvent: false } option object that we send in to the patchValue function, which makes sure that one subscription callback does not trigger the other.


Adding the select/unselect all checkbox to our template

To finalise our component template we simply create a new checkbox input element in our form and set the formControlName to selectAll.


Wrapping up

Thanks for reading! Hope you found it useful. The final code can be found at: