Installation
import { WrCheckbox, WrCheckboxGroup } from 'ngwr/checkbox';
import { FormsModule } from '@angular/forms';
@Component({ imports: [WrCheckbox, WrCheckboxGroup, FormsModule] })
export class MyComponent {}Standalone
Signal-forms native — bind the boolean checked model via [(checked)], [formField], or classic [(ngModel)].
<!-- signal-forms native: [(checked)], [formField], or classic [(ngModel)] -->
<wr-checkbox [(checked)]="agree">I agree</wr-checkbox>Inside a group
The group manages an array of values. Each child contributes its value when checked.
<wr-checkbox-group [(value)]="features">
<wr-checkbox checkboxValue="autosave">Autosave</wr-checkbox>
<wr-checkbox checkboxValue="notifications">Notifications</wr-checkbox>
<wr-checkbox checkboxValue="darkmode">Dark mode</wr-checkbox>
</wr-checkbox-group>Indeterminate
A parent [indeterminate] shows the mixed state (a dash) when only some children are checked — the classic 'select all'. It's visual and controlled: you set it, and clear it on the next toggle.
<!-- A parent "select all": mixed when only some children are checked. -->
<wr-checkbox [checked]="allChecked()" (checkedChange)="toggleAll()" [indeterminate]="someChecked()">
Select all
</wr-checkbox>
@for (p of permItems; track p) {
<wr-checkbox [checked]="perms().includes(p)" (checkedChange)="togglePerm(p)">{{ p }}</wr-checkbox>
}Disabled
<wr-checkbox [disabled]="true">Disabled</wr-checkbox>Use it in a form
Signal forms is the native path — [formField] binds the checked model directly. Reactive forms and [(ngModel)] go through Angular 22's forms bridge, which binds a signal-forms control with no ControlValueAccessor involved: the library ships none, and formControlName still works. That bridge is not an accessor, and the guide is what it carries and what it drops — updateOn, required, and a { emitEvent: false } write that never repaints. Mind which model each half binds, too: a single checkbox is a boolean, the group is the array of checkboxValues.
<!-- Signal forms — the native path. -->
<wr-checkbox [formField]="form.agree">I agree</wr-checkbox>
<!-- Reactive forms. A single <wr-checkbox> is a FormCheckboxControl, so the
control it binds holds a BOOLEAN — the checkbox's `checked` model, not
`checkboxValue` (which is group identity and stays out of forms). -->
<form [formGroup]="form">
<wr-checkbox formControlName="agree">I agree to the terms</wr-checkbox>
<!-- A <wr-checkbox-group> is a FormValueControl<unknown[]>, so ITS control
holds the array of checked `checkboxValue`s. -->
<wr-checkbox-group formControlName="features">
<wr-checkbox checkboxValue="autosave">Autosave</wr-checkbox>
<wr-checkbox checkboxValue="notifications">Notifications</wr-checkbox>
</wr-checkbox-group>
</form>
<!-- Template-driven — the same bridge. -->
<wr-checkbox [(ngModel)]="agree" name="agree">I agree</wr-checkbox>import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { WrCheckbox, WrCheckboxGroup } from 'ngwr/checkbox';
@Component({
imports: [ReactiveFormsModule, WrCheckbox, WrCheckboxGroup],
templateUrl: './my.html',
})
export class MyComponent {
protected readonly form = new FormGroup({
agree: new FormControl(false, { nonNullable: true, validators: [Validators.requiredTrue] }),
features: new FormControl<string[]>(['autosave'], { nonNullable: true }),
});
}Checkbox API
| Name | Description | Type | Default |
|---|---|---|---|
id | Stable id used to associate the native input with its label. Lands on the inner <input>; the host never keeps it. | string | Randomly generated |
checkboxValue | This checkbox's identity when inside a <wr-checkbox-group> — the value added to / removed from the group's array. Ignored in standalone mode. (Named checkboxValue, not value, because FormCheckboxControl reserves value.) | unknown | null |
ariaLabel | Accessible name for a checkbox used WITHOUT projected text — a selection cell in a table, say. The wrapping <label> names the control whenever content is projected; with none, the native input has no name, and an aria-label put on the host lands on a <wr-checkbox> element that no screen reader ever announces. | string | null | null |
checked | Checked state — the form value. Bound by [formField], two-way via [(checked)], or [(ngModel)]. Ignored inside a <wr-checkbox-group>, where the group's array is the source of truth. | boolean | false |
(touch) | Emitted on blur so a bound field can mark itself touched. | void | — |
disabled | Disable the checkbox. Bound automatically from the field's disabled state when used with [formField]. | boolean | false |
readonly | Refuse edits while staying focusable and submittable. Bound automatically from the field's readonly state when used with [formField]. A native <input type="checkbox"> ignores the readonly attribute, so this cancels the click's activation behaviour instead — which covers Space too, since a checkbox turns Space into a click — and mirrors the state as aria-readonly, which role checkbox supports. | boolean | false |
size | Control size — shares the --wr-control-* contract. Unset falls back to the checkbox.size app default from provideWrConfig(). | WrCheckboxSize | null | 'md' |
icon | Optional icon name rendered inside the box when checked, in place of the default checkmark. Use any registered NGWR icon. | WrIconName | null | null |
indeterminate | Show the indeterminate ("mixed") state — a dash instead of a check. Visual only and controlled: set it yourself for a parent "select all" whose children are partly checked, and clear it on the next toggle. Takes visual precedence over checked; the native input reports aria-checked="mixed". | boolean | false |
Checkbox Group API
| Name | Description | Type | Default |
|---|---|---|---|
disabled | Disable every child checkbox. Bound automatically from the field's disabled state when used with [formField]. | boolean | false |
readonly | Refuse edits on every child while they stay focusable and the value still submits. Bound automatically from the field's readonly state when used with [formField]. No aria-readonly on the host: role group does not support it (the state is not global), so each child box mirrors its own instead. | boolean | false |
value | The checked items' values. Bound by [formField], or two-way via [(value)]. | unknown[] | [] |
(touch) | Emitted when a child toggles so a bound field can mark itself touched. | void | — |
CSS variables
Custom properties ngwr/checkbox publishes. Each default below is declared on the component's own selector, so a :root override is shadowed by it — set them on that selector, on a wrapper you scope yourself, or inline on the element. Unlike the BEM class names, these are the supported way to restyle the component.
| Variable | Default | Declared on |
|---|---|---|
--wr-checkbox-bg | var(--wr-color-surface) | .wr-checkbox +2 variant overrides |
--wr-checkbox-border | var(--wr-color-outline) | .wr-checkbox +3 variant overrides |
--wr-checkbox-color | var(--wr-color-on-surface) | .wr-checkbox +1 variant override |
--wr-checkbox-font-size | var(--wr-text-sm) | .wr-checkbox +2 variant overrides |
--wr-checkbox-line-height | var(--wr-control-line-height-md) | .wr-checkbox +2 variant overrides |
--wr-checkbox-mark | transparent | .wr-checkbox +2 variant overrides |
--wr-checkbox-radius | var(--wr-control-radius-md) | .wr-checkbox +2 variant overrides |
--wr-checkbox-size | 1.125rem | .wr-checkbox +2 variant overrides |