Angular 2+ Reactive Form - Submitting Checkboxes

May 16, 2018

Complicated Problem 4: I have a bunch of checkboxes and need to submit an array of selected ids

There’s the HTML appropriate/semantic way to deal with checkboxes/radios, and then there’s the way the business requirements want them to be done. I’m all about picking and choosing my battles, and this is a battle I don’t try and fight. So I present to you a way to handle submitting arrays with checkboxes so you can focus on fighting your bigger fights.

Control Value Accessor to the rescue again!

Avril Lavigne

Let’s start with our CVA implementation, then our component markup.

export class MyCheckboxesComponent implements ControlValueAccessor {
  @Input() data: any[];

  @Input('value') _value = [];
  onChange: any = () => { };
  onTouched: any = () => { };

  get value() {
    return this._value;
  }

  set value(val) {
    this._value = val;
    this.onChange(val);
    this.onTouched();
  }

  registerOnChange( fn : any ) : void {
    this.onChange = fn;
  }

  registerOnTouched( fn : any ) : void {
    this.onTouched = fn;
  }

  writeValue(value:any) {
    this.value = value;
  }

  selectCheckbox(checkboxId) {
    const updatedArray = this.value;
    updatedArray.push(checkboxId);
    this.writeValue(updatedArray);
  }

  removeCheckbox(checkboxId) {
    var index = this.value.indexOf(checkboxId);
    if (index > -1) {
      this.value.splice(index, 1);
    }
  }

}
<ng-container *ngFor="let item of data">
  <div class="form-check form-check-inline">
    <ng-container *ngIf="value && value.includes(item.id)">
      <input class="form-check-input" type="checkbox" value="{{item.id}}" checked (click)=removeCheckbox(item.id)>
    </ng-container>
    <ng-container *ngIf="!value || !value.includes(item.id)">
      <input class="form-check-input" type="checkbox" value="{{item.id}}" (click)=selectCheckbox(item.id)>
    </ng-container>
    <label class="form-check-label" >{{item.name}}</label>
  </div>
</ng-container>
<form>
  <div class="form-group">
    <label for="subcategory">Subcategory</label>
    <my-checkboxes formControlName="subcategory" [data]="subcategories"></my-checkboxes>
  </div>
</form>

Seem familiar yet?

Business requirements - 0

Us - 1

Demo code available at https://github.com/tehfedaykin/complicated-forms-app