diff --git a/src/components-examples/material/checkbox/checkbox-configurable/checkbox-configurable-example.html b/src/components-examples/material/checkbox/checkbox-configurable/checkbox-configurable-example.html index 4591963c3e23..5e69d1164262 100644 --- a/src/components-examples/material/checkbox/checkbox-configurable/checkbox-configurable-example.html +++ b/src/components-examples/material/checkbox/checkbox-configurable/checkbox-configurable-example.html @@ -27,11 +27,12 @@

Result

+ class="example-margin" + [(ngModel)]="checked" + [(indeterminate)]="indeterminate" + [labelPosition]="labelPosition()" + [disabled]="disabled()" + > I'm a checkbox
diff --git a/src/components-examples/material/checkbox/checkbox-configurable/checkbox-configurable-example.ts b/src/components-examples/material/checkbox/checkbox-configurable/checkbox-configurable-example.ts index 59226280dbc7..988ca6c6ecaa 100644 --- a/src/components-examples/material/checkbox/checkbox-configurable/checkbox-configurable-example.ts +++ b/src/components-examples/material/checkbox/checkbox-configurable/checkbox-configurable-example.ts @@ -1,8 +1,8 @@ -import {Component} from '@angular/core'; -import {MatRadioModule} from '@angular/material/radio'; +import {ChangeDetectionStrategy, Component, model} from '@angular/core'; import {FormsModule} from '@angular/forms'; -import {MatCheckboxModule} from '@angular/material/checkbox'; import {MatCardModule} from '@angular/material/card'; +import {MatCheckboxModule} from '@angular/material/checkbox'; +import {MatRadioModule} from '@angular/material/radio'; /** * @title Configurable checkbox @@ -13,10 +13,11 @@ import {MatCardModule} from '@angular/material/card'; styleUrl: 'checkbox-configurable-example.css', standalone: true, imports: [MatCardModule, MatCheckboxModule, FormsModule, MatRadioModule], + changeDetection: ChangeDetectionStrategy.OnPush, }) export class CheckboxConfigurableExample { - checked = false; - indeterminate = false; - labelPosition: 'before' | 'after' = 'after'; - disabled = false; + readonly checked = model(false); + readonly indeterminate = model(false); + readonly labelPosition = model<'before' | 'after'>('after'); + readonly disabled = model(false); } diff --git a/src/components-examples/material/checkbox/checkbox-harness/checkbox-harness-example.html b/src/components-examples/material/checkbox/checkbox-harness/checkbox-harness-example.html index 016dd3b2fdcf..ec690de63f0f 100644 --- a/src/components-examples/material/checkbox/checkbox-harness/checkbox-harness-example.html +++ b/src/components-examples/material/checkbox/checkbox-harness/checkbox-harness-example.html @@ -1,11 +1,12 @@ + required + [checked]="true" + name="first-name" + value="first-value" + aria-label="First checkbox" +> First - + Second diff --git a/src/components-examples/material/checkbox/checkbox-harness/checkbox-harness-example.spec.ts b/src/components-examples/material/checkbox/checkbox-harness/checkbox-harness-example.spec.ts index fce1d8b50331..a1d933725071 100644 --- a/src/components-examples/material/checkbox/checkbox-harness/checkbox-harness-example.spec.ts +++ b/src/components-examples/material/checkbox/checkbox-harness/checkbox-harness-example.spec.ts @@ -38,7 +38,7 @@ describe('CheckboxHarnessExample', () => { }); it('should toggle checkbox', async () => { - fixture.componentInstance.disabled = false; + fixture.componentRef.setInput('disabled', false); fixture.changeDetectorRef.markForCheck(); const [checkedCheckbox, uncheckedCheckbox] = await loader.getAllHarnesses(MatCheckboxHarness); await checkedCheckbox.toggle(); diff --git a/src/components-examples/material/checkbox/checkbox-harness/checkbox-harness-example.ts b/src/components-examples/material/checkbox/checkbox-harness/checkbox-harness-example.ts index b705d6fb1042..15096bd64c23 100644 --- a/src/components-examples/material/checkbox/checkbox-harness/checkbox-harness-example.ts +++ b/src/components-examples/material/checkbox/checkbox-harness/checkbox-harness-example.ts @@ -1,4 +1,4 @@ -import {Component} from '@angular/core'; +import {ChangeDetectionStrategy, Component, input} from '@angular/core'; import {MatCheckboxModule} from '@angular/material/checkbox'; /** @@ -9,7 +9,8 @@ import {MatCheckboxModule} from '@angular/material/checkbox'; templateUrl: 'checkbox-harness-example.html', standalone: true, imports: [MatCheckboxModule], + changeDetection: ChangeDetectionStrategy.OnPush, }) export class CheckboxHarnessExample { - disabled = true; + readonly disabled = input(true); } diff --git a/src/components-examples/material/checkbox/checkbox-overview/checkbox-overview-example.html b/src/components-examples/material/checkbox/checkbox-overview/checkbox-overview-example.html index ff06d1f31192..c0ef9c350835 100644 --- a/src/components-examples/material/checkbox/checkbox-overview/checkbox-overview-example.html +++ b/src/components-examples/material/checkbox/checkbox-overview/checkbox-overview-example.html @@ -5,21 +5,20 @@
- - {{task.name}} + + {{task().name}}
    - @for (subtask of task.subtasks; track subtask) { + @for (subtask of task().subtasks; track subtask; let i = $index) {
  • - + {{subtask.name}}
  • diff --git a/src/components-examples/material/checkbox/checkbox-overview/checkbox-overview-example.ts b/src/components-examples/material/checkbox/checkbox-overview/checkbox-overview-example.ts index afc6b11d655f..2ec2a90dd804 100644 --- a/src/components-examples/material/checkbox/checkbox-overview/checkbox-overview-example.ts +++ b/src/components-examples/material/checkbox/checkbox-overview/checkbox-overview-example.ts @@ -1,12 +1,10 @@ -import {Component} from '@angular/core'; -import {ThemePalette} from '@angular/material/core'; +import {ChangeDetectionStrategy, Component, computed, signal} from '@angular/core'; import {FormsModule} from '@angular/forms'; import {MatCheckboxModule} from '@angular/material/checkbox'; export interface Task { name: string; completed: boolean; - color: ThemePalette; subtasks?: Task[]; } @@ -19,37 +17,37 @@ export interface Task { styleUrl: 'checkbox-overview-example.css', standalone: true, imports: [MatCheckboxModule, FormsModule], + changeDetection: ChangeDetectionStrategy.OnPush, }) export class CheckboxOverviewExample { - task: Task = { - name: 'Indeterminate', + readonly task = signal({ + name: 'Parent task', completed: false, - color: 'primary', subtasks: [ - {name: 'Primary', completed: false, color: 'primary'}, - {name: 'Accent', completed: false, color: 'accent'}, - {name: 'Warn', completed: false, color: 'warn'}, + {name: 'Child task 1', completed: false}, + {name: 'Child task 2', completed: false}, + {name: 'Child task 3', completed: false}, ], - }; + }); - allComplete: boolean = false; - - updateAllComplete() { - this.allComplete = this.task.subtasks != null && this.task.subtasks.every(t => t.completed); - } - - someComplete(): boolean { - if (this.task.subtasks == null) { + readonly partiallyComplete = computed(() => { + const task = this.task(); + if (!task.subtasks) { return false; } - return this.task.subtasks.filter(t => t.completed).length > 0 && !this.allComplete; - } + return task.subtasks.some(t => t.completed) && !task.subtasks.every(t => t.completed); + }); - setAll(completed: boolean) { - this.allComplete = completed; - if (this.task.subtasks == null) { - return; - } - this.task.subtasks.forEach(t => (t.completed = completed)); + update(completed: boolean, index?: number) { + this.task.update(task => { + if (index === undefined) { + task.completed = completed; + task.subtasks?.forEach(t => (t.completed = completed)); + } else { + task.subtasks![index].completed = completed; + task.completed = task.subtasks?.every(t => t.completed) ?? true; + } + return {...task}; + }); } } diff --git a/src/components-examples/material/checkbox/checkbox-reactive-forms/checkbox-reactive-forms-example.ts b/src/components-examples/material/checkbox/checkbox-reactive-forms/checkbox-reactive-forms-example.ts index 1ef154b96e93..da549269c1c2 100644 --- a/src/components-examples/material/checkbox/checkbox-reactive-forms/checkbox-reactive-forms-example.ts +++ b/src/components-examples/material/checkbox/checkbox-reactive-forms/checkbox-reactive-forms-example.ts @@ -1,6 +1,6 @@ -import {Component} from '@angular/core'; -import {FormBuilder, FormsModule, ReactiveFormsModule} from '@angular/forms'; import {JsonPipe} from '@angular/common'; +import {ChangeDetectionStrategy, Component, inject} from '@angular/core'; +import {FormBuilder, FormsModule, ReactiveFormsModule} from '@angular/forms'; import {MatCheckboxModule} from '@angular/material/checkbox'; /** @title Checkboxes with reactive forms */ @@ -10,13 +10,14 @@ import {MatCheckboxModule} from '@angular/material/checkbox'; styleUrl: 'checkbox-reactive-forms-example.css', standalone: true, imports: [FormsModule, ReactiveFormsModule, MatCheckboxModule, JsonPipe], + changeDetection: ChangeDetectionStrategy.OnPush, }) export class CheckboxReactiveFormsExample { - toppings = this._formBuilder.group({ + private readonly _formBuilder = inject(FormBuilder); + + readonly toppings = this._formBuilder.group({ pepperoni: false, extracheese: false, mushroom: false, }); - - constructor(private _formBuilder: FormBuilder) {} } diff --git a/src/material/checkbox/checkbox-config.ts b/src/material/checkbox/checkbox-config.ts index 239c38e15ed6..9c5aeb561b79 100644 --- a/src/material/checkbox/checkbox-config.ts +++ b/src/material/checkbox/checkbox-config.ts @@ -10,7 +10,11 @@ import {ThemePalette} from '@angular/material/core'; /** Default `mat-checkbox` options that can be overridden. */ export interface MatCheckboxDefaultOptions { - /** Default theme color palette to be used for checkboxes. */ + /** + * Default theme color palette to be used for checkboxes. This API is supported in M2 themes + * only, it has no effect in M3 themes. For information on applying color variants in M3, see + * https://material.angular.io/guide/theming#using-component-color-variants + */ color?: ThemePalette; /** Default checkbox click action for checkboxes. */ clickAction?: MatCheckboxClickAction; diff --git a/src/material/checkbox/checkbox.md b/src/material/checkbox/checkbox.md index ac83e70eb271..63e1b8a7a792 100644 --- a/src/material/checkbox/checkbox.md +++ b/src/material/checkbox/checkbox.md @@ -4,6 +4,7 @@ enhanced with Material Design styling and animations. ### Checkbox label + The checkbox label is provided as the content to the `` element. The label can be positioned before or after the checkbox by setting the `labelPosition` property to `'before'` or `'after'`. @@ -14,16 +15,19 @@ If you don't want the label to appear next to the checkbox, you can use specify an appropriate label. ### Use with `@angular/forms` + `` is compatible with `@angular/forms` and supports both `FormsModule` and `ReactiveFormsModule`. ### Indeterminate state + `` supports an `indeterminate` state, similar to the native ``. While the `indeterminate` property of the checkbox is true, it will render as indeterminate regardless of the `checked` value. Any interaction with the checkbox by a user (i.e., clicking) will remove the indeterminate state. ### Click action config + When user clicks on the `mat-checkbox`, the default behavior is toggle `checked` value and set `indeterminate` to `false`. This behavior can be customized by [providing a new value](https://angular.io/guide/dependency-injection) @@ -38,22 +42,29 @@ providers: [ The possible values are: #### `noop` + Do not change the `checked` value or `indeterminate` value. Developers have the power to implement customized click actions. #### `check` + Toggle `checked` value of the checkbox, ignore `indeterminate` value. If the checkbox is in `indeterminate` state, the checkbox will display as an `indeterminate` checkbox regardless the `checked` value. #### `check-indeterminate` + Default behavior of `mat-checkbox`. Always set `indeterminate` to `false` when user click on the `mat-checkbox`. This matches the behavior of native ``. ### Theming -The color of a `` can be changed by using the `color` property. By default, checkboxes -use the theme's accent color. This can be changed to `'primary'` or `'warn'`. + +The color of a `` can be changed by specifying a `$color-variant` when applying the +`mat.checkbox-theme` or `mat.checkbox-color` mixins (see the +[theming guide](/guide/theming#using-component-color-variants) to learn more.) By default, +checkboxes use the theme's primary palette. This can be changed to `'secondary'`, `'tertiary'`, +or `'error'`. ### Accessibility diff --git a/src/material/checkbox/checkbox.ts b/src/material/checkbox/checkbox.ts index 7591b46dac0c..92f424d32214 100644 --- a/src/material/checkbox/checkbox.ts +++ b/src/material/checkbox/checkbox.ts @@ -6,27 +6,28 @@ * found in the LICENSE file at https://angular.io/license */ +import {FocusableOption} from '@angular/cdk/a11y'; import { + ANIMATION_MODULE_TYPE, AfterViewInit, Attribute, - booleanAttribute, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, - forwardRef, Inject, Input, NgZone, - numberAttribute, OnChanges, Optional, Output, SimpleChanges, ViewChild, ViewEncapsulation, - ANIMATION_MODULE_TYPE, + booleanAttribute, + forwardRef, + numberAttribute, } from '@angular/core'; import { AbstractControl, @@ -36,8 +37,7 @@ import { ValidationErrors, Validator, } from '@angular/forms'; -import {_MatInternalFormField, MatRipple} from '@angular/material/core'; -import {FocusableOption} from '@angular/cdk/a11y'; +import {MatRipple, _MatInternalFormField} from '@angular/material/core'; import { MAT_CHECKBOX_DEFAULT_OPTIONS, MAT_CHECKBOX_DEFAULT_OPTIONS_FACTORY, @@ -202,7 +202,11 @@ export class MatCheckbox // TODO(crisbeto): this should be a ThemePalette, but some internal apps were abusing // the lack of type checking previously and assigning random strings. - /** Palette color of the checkbox. */ + /** + * Palette color of the checkbox. This API is supported in M2 themes only, it has no effect in M3 + * themes. For information on applying color variants in M3, see + * https://material.angular.io/guide/theming#using-component-color-variants + */ @Input() color: string | undefined; /**