/
githubmirror
/
angular
Обзор
Документация
Войти
/
githubmirror
/
angular
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
packages/forms/signals/src/controls/interop_ng_control.ts
147 строк
4 KB
splincode
refactor(forms): replace `any` with `unknown` in interop control value types
29 апр 2026, 23:35
29 апр 2026, 23:35
54a985c
Код
Авторство
О чём код?
/** * @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 {ɵRuntimeError as RuntimeError} from '@angular/core'; import {RuntimeErrorCode} from '../errors'; import {signalErrorsToValidationErrors} from '../compat/validation_errors'; import { ControlValueAccessor, Validators, type AbstractControl, type FormControlStatus, type ValidationErrors, type ValidatorFn, } from '@angular/forms'; import type {ReadonlyFieldState} from '../api/types'; // TODO: Also consider supporting (if possible): // - hasError // - getError // - reset // - name // - path // - markAs[Touched,Dirty,etc.] /** * Represents a combination of `NgControl` and `AbstractControl`. * * Note: We have this separate interface, rather than implementing the relevant parts of the two * controls with something like `InteropNgControl implements Pick<NgControl, ...>, Pick<AbstractControl, ...>` * because it confuses the internal JS minifier which can cause collisions in field names. */ interface CombinedControl { value: unknown; valid: boolean; invalid: boolean; touched: boolean; untouched: boolean; disabled: boolean; enabled: boolean; errors: ValidationErrors | null; pristine: boolean; dirty: boolean; status: FormControlStatus; control: AbstractControl<any, any>; valueAccessor: ControlValueAccessor | null; hasValidator(validator: ValidatorFn): boolean; updateValueAndValidity(): void; } /** * A fake version of `NgControl` provided by the `Field` directive. This allows interoperability * with a wider range of components designed to work with reactive forms, in particular ones that * inject the `NgControl`. The interop control does not implement *all* properties and methods of * the real `NgControl`, but does implement some of the most commonly used ones that have a clear * equivalent in signal forms. */ export class InteropNgControl implements CombinedControl { constructor(protected field: () => ReadonlyFieldState<unknown>) {} readonly control: AbstractControl<any, any> = this as unknown as AbstractControl<any, any>; get value(): unknown { // CVA controls are not aware of user debouncing and will expect `NgControl.value` to reflect their latest writes. return this.field().controlValue(); } get valid(): boolean { return this.field().valid(); } get invalid(): boolean { return this.field().invalid(); } get pending(): boolean | null { return this.field().pending(); } get disabled(): boolean { return this.field().disabled(); } get enabled(): boolean { return !this.field().disabled(); } get errors(): ValidationErrors | null { return signalErrorsToValidationErrors(this.field().errors()); } get pristine(): boolean { return !this.field().dirty(); } get dirty(): boolean { return this.field().dirty(); } get touched(): boolean { return this.field().touched(); } get untouched(): boolean { return !this.field().touched(); } get status(): FormControlStatus { if (this.field().disabled()) { return 'DISABLED'; } if (this.field().valid()) { return 'VALID'; } if (this.field().invalid()) { return 'INVALID'; } if (this.field().pending()) { return 'PENDING'; } throw new RuntimeError( RuntimeErrorCode.UNKNOWN_STATUS, ngDevMode && 'Unknown form control status', ); } valueAccessor: ControlValueAccessor | null = null; hasValidator(validator: ValidatorFn): boolean { // This addresses a common case where users look for the presence of `Validators.required` to // determine whether or not to show a required "*" indicator in the UI. if (validator === Validators.required) { return this.field().required(); } return false; } updateValueAndValidity() { // No-op since value and validity are always up to date in signal forms. // We offer this method so that reactive forms code attempting to call it doesn't error. } }