/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.dev/license */ import {_IdGenerator, FocusableOption} from '@angular/cdk/a11y'; import { ANIMATION_MODULE_TYPE, AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, Input, NgZone, OnChanges, Output, SimpleChanges, ViewChild, ViewEncapsulation, booleanAttribute, forwardRef, numberAttribute, inject, HostAttributeToken, } from '@angular/core'; import { AbstractControl, ControlValueAccessor, NG_VALIDATORS, NG_VALUE_ACCESSOR, ValidationErrors, Validator, } from '@angular/forms'; import {MatRipple, _MatInternalFormField, _StructuralStylesLoader} from '@angular/material/core'; import { MAT_CHECKBOX_DEFAULT_OPTIONS, MAT_CHECKBOX_DEFAULT_OPTIONS_FACTORY, MatCheckboxDefaultOptions, } from './checkbox-config'; import {_CdkPrivateStyleLoader} from '@angular/cdk/private'; /** * Represents the different states that require custom transitions between them. * @docs-private */ export enum TransitionCheckState { /** The initial state of the component before any user interaction. */ Init, /** The state representing the component when it's becoming checked. */ Checked, /** The state representing the component when it's becoming unchecked. */ Unchecked, /** The state representing the component when it's becoming indeterminate. */ Indeterminate, } /** * @deprecated Will stop being exported. * @breaking-change 19.0.0 */ export const MAT_CHECKBOX_CONTROL_VALUE_ACCESSOR: any = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MatCheckbox), multi: true, }; /** Change event object emitted by checkbox. */ export class MatCheckboxChange { /** The source checkbox of the event. */ source: MatCheckbox; /** The new `checked` value of the checkbox. */ checked: boolean; } // Default checkbox configuration. const defaults = MAT_CHECKBOX_DEFAULT_OPTIONS_FACTORY(); @Component({ selector: 'mat-checkbox', templateUrl: 'checkbox.html', styleUrl: 'checkbox.css', host: { 'class': 'mat-mdc-checkbox', '[attr.tabindex]': 'null', '[attr.aria-label]': 'null', '[attr.aria-labelledby]': 'null', '[class._mat-animation-noopable]': `_animationMode === 'NoopAnimations'`, '[class.mdc-checkbox--disabled]': 'disabled', '[id]': 'id', // Add classes that users can use to more easily target disabled or checked checkboxes. '[class.mat-mdc-checkbox-disabled]': 'disabled', '[class.mat-mdc-checkbox-checked]': 'checked', '[class.mat-mdc-checkbox-disabled-interactive]': 'disabledInteractive', '[class]': 'color ? "mat-" + color : "mat-accent"', }, providers: [ MAT_CHECKBOX_CONTROL_VALUE_ACCESSOR, { provide: NG_VALIDATORS, useExisting: MatCheckbox, multi: true, }, ], exportAs: 'matCheckbox', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatRipple, _MatInternalFormField], }) export class MatCheckbox implements AfterViewInit, OnChanges, ControlValueAccessor, Validator, FocusableOption { _elementRef = inject>(ElementRef); private _changeDetectorRef = inject(ChangeDetectorRef); private _ngZone = inject(NgZone); _animationMode? = inject(ANIMATION_MODULE_TYPE, {optional: true}); private _options = inject(MAT_CHECKBOX_DEFAULT_OPTIONS, { optional: true, }); /** Focuses the checkbox. */ focus() { this._inputElement.nativeElement.focus(); } /** Creates the change event that will be emitted by the checkbox. */ protected _createChangeEvent(isChecked: boolean) { const event = new MatCheckboxChange(); event.source = this; event.checked = isChecked; return event; } /** Gets the element on which to add the animation CSS classes. */ protected _getAnimationTargetElement() { return this._inputElement?.nativeElement; } /** CSS classes to add when transitioning between the different checkbox states. */ protected _animationClasses = { uncheckedToChecked: 'mdc-checkbox--anim-unchecked-checked', uncheckedToIndeterminate: 'mdc-checkbox--anim-unchecked-indeterminate', checkedToUnchecked: 'mdc-checkbox--anim-checked-unchecked', checkedToIndeterminate: 'mdc-checkbox--anim-checked-indeterminate', indeterminateToChecked: 'mdc-checkbox--anim-indeterminate-checked', indeterminateToUnchecked: 'mdc-checkbox--anim-indeterminate-unchecked', }; /** * Attached to the aria-label attribute of the host element. In most cases, aria-labelledby will * take precedence so this may be omitted. */ @Input('aria-label') ariaLabel: string = ''; /** * Users can specify the `aria-labelledby` attribute which will be forwarded to the input element */ @Input('aria-labelledby') ariaLabelledby: string | null = null; /** The 'aria-describedby' attribute is read after the element's label and field type. */ @Input('aria-describedby') ariaDescribedby: string; /** * Users can specify the `aria-expanded` attribute which will be forwarded to the input element */ @Input({alias: 'aria-expanded', transform: booleanAttribute}) ariaExpanded: boolean; /** * Users can specify the `aria-controls` attribute which will be forwarded to the input element */ @Input('aria-controls') ariaControls: string; /** Users can specify the `aria-owns` attribute which will be forwarded to the input element */ @Input('aria-owns') ariaOwns: string; private _uniqueId: string; /** A unique id for the checkbox input. If none is supplied, it will be auto-generated. */ @Input() id: string; /** Returns the unique id for the visual hidden input. */ get inputId(): string { return `${this.id || this._uniqueId}-input`; } /** Whether the checkbox is required. */ @Input({transform: booleanAttribute}) required: boolean; /** Whether the label should appear after or before the checkbox. Defaults to 'after' */ @Input() labelPosition: 'before' | 'after' = 'after'; /** Name value will be applied to the input element if present */ @Input() name: string | null = null; /** Event emitted when the checkbox's `checked` value changes. */ @Output() readonly change = new EventEmitter(); /** Event emitted when the checkbox's `indeterminate` value changes. */ @Output() readonly indeterminateChange: EventEmitter = new EventEmitter(); /** The value attribute of the native input element */ @Input() value: string; /** Whether the checkbox has a ripple. */ @Input({transform: booleanAttribute}) disableRipple: boolean; /** The native `` element */ @ViewChild('input') _inputElement: ElementRef; /** The native `