The recommended approach involves leveraging the power of reactive forms to handle grouped checkboxes efficiently. By utilizing a FormGroup in Angular, you can easily create validators to ensure at least one checkbox is selected within a specific group.
To implement this functionality, simply nest another FormGroup
inside your existing one and attach a validator:
form = new FormGroup({
// ...more form controls...
myCheckboxGroup: new FormGroup({
myCheckbox1: new FormControl(false),
myCheckbox2: new FormControl(false),
myCheckbox3: new FormControl(false),
}, requireCheckboxesToBeCheckedValidator()),
// ...more form controls...
});
You can customize the validator to check for a specific number of checkboxes by passing an argument, such as
requireCheckboxesToBeCheckedValidator(2)
:
import { FormGroup, ValidatorFn } from '@angular/forms';
export function requireCheckboxesToBeCheckedValidator(minRequired = 1): ValidatorFn {
return function validate (formGroup: FormGroup) {
let checked = 0;
Object.keys(formGroup.controls).forEach(key => {
const control = formGroup.controls[key];
if (control.value === true) {
checked ++;
}
});
if (checked < minRequired) {
return {
requireCheckboxesToBeChecked: true,
};
}
return null;
};
}
In your HTML template, remember to include the 'formGroupName' directive to encapsulate your checkboxes within the group. The compiler will notify you of any errors if it's not set up correctly:
<ng-container [formGroup]="form">
<!-- ...more form controls... -->
<div class="form-group" formGroupName="myCheckboxGroup">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" formControlName="myCheckbox1" id="myCheckbox1">
<label class="custom-control-label" for="myCheckbox1">Option 1</label>
</div>
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" formControlName="myCheckbox2" id="myCheckbox2">
<label class="custom-control-label" for="myCheckbox2">Option 2</label>
</div>
<div class="invalid-feedback" *ngIf="form.controls['myCheckboxGroup'].errors && form.controls['myCheckboxGroup'].errors.requireCheckboxesToBeChecked">Please select at least one option.</div>
</div>
<!-- ...more form controls... -->
</ng-container>
*For a more dynamic implementation, consider storing form data in an array and generating the template using ngFor.
Avoid misusing hidden FormControl attributes like in some examples. A FormControl is designed for input values only, while additional metadata should be managed separately for clarity and maintainability. View a live demo here: https://stackblitz.com/edit/angular-at-least-one-checkbox-checked