Custom Checkbox Component with Angular

February 2021

Your first guess when creating a custom checkbox component might be to just create a div with something inside. But this approach has several drawbacks:

This is where the Angular Control Value Accessor (CVA) comes into play. If you implement this interface, you teach Angular how to access "the" value associated with the component and thus enabling ngModel. There's a full article at Angular Control Value Accessor Tutorial. Here we're not explaining in detail how CVA is working, but instead we'll just show you how to implement a custom checkbox right away:

<label class="checkbox-container">
  <input
    class="checkbox-input"
    type="checkbox"
    [ngModel]="checked"
    (ngModelChange)="onModelChange($event)"
  />
  <div class="checkbox-border">
    <div class="checkbox-filling" *ngIf="checked"></div>
  </div>
  <ng-content> </ng-content>
</label>
import { Component, OnInit, forwardRef } from "@angular/core";
import {
  ControlValueAccessor,
  FormControl,
  NG_VALUE_ACCESSOR
} from "@angular/forms";

@Component({
  selector: "app-custom-checkbox",
  templateUrl: "./custom-checkbox.component.html",
  styleUrls: ["./custom-checkbox.component.scss"],

  // Step 1: copy paste this providers property
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CustomCheckboxComponent),
      multi: true
    }
  ]
})
// Step 2: Add "implements ControlValueAccessor"
export class CustomCheckboxComponent implements ControlValueAccessor, OnInit {
  // Step 3: Copy paste this stuff here
  onChange: any = () => {};
  onTouch: any = () => {};

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

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

  constructor() {}

  ngOnInit() {}

  // Step 4: Define what should happen in this component, if something changes outside
  checked: boolean = false;
  writeValue(checked: boolean) {
    this.checked = checked;
  }

  onModelChange(e: boolean) {
    // Step 5a: bind the changes to the local value
    this.checked = e;

    // Step 5b: Handle what should happen on the outside, if something changes on the inside
    this.onChange(e);
  }
}

Here's the code on Stackblitz for the custom checkbox with angular.

And here's what you'll get:

I share things I consider useful