refactor(forms): introduce signal for required validator status

Introduces an internal signal that tracks whether `Validators.required` is in the set of validators
for an `AbstractControl`. This signal is updated whenever the validators are changed.
This commit is contained in:
Alex Rickabaugh
2026-01-28 16:00:04 -08:00
committed by Matthew Beck (Berry)
parent 9d19d2321a
commit d1576ee92b
2 changed files with 19 additions and 0 deletions
@@ -31,6 +31,7 @@ import {
hasValidator,
removeValidators,
toObservable,
Validators,
} from '../validators';
import type {FormArray} from './form_array';
import type {FormGroup} from './form_group';
@@ -502,6 +503,9 @@ export abstract class AbstractControl<
/** @internal */
_updateOn?: FormHooks;
/** @internal */
_hasRequired = signal(false);
private _parent: FormGroup | FormArray | null = null;
private _asyncValidationSubscription: any;
@@ -581,6 +585,7 @@ export abstract class AbstractControl<
}
set validator(validatorFn: ValidatorFn | null) {
this._rawValidators = this._composedValidatorFn = validatorFn;
this._updateHasRequiredValidator();
}
/**
@@ -1784,6 +1789,7 @@ export abstract class AbstractControl<
private _assignValidators(validators: ValidatorFn | ValidatorFn[] | null): void {
this._rawValidators = Array.isArray(validators) ? validators.slice() : validators;
this._composedValidatorFn = coerceToValidator(this._rawValidators);
this._updateHasRequiredValidator();
}
/**
@@ -1795,4 +1801,8 @@ export abstract class AbstractControl<
this._rawAsyncValidators = Array.isArray(validators) ? validators.slice() : validators;
this._composedAsyncValidatorFn = coerceToAsyncValidator(this._rawAsyncValidators);
}
private _updateHasRequiredValidator(): void {
untracked(() => this._hasRequired.set(this.hasValidator(Validators.required)));
}
}