refactor(forms): Remove readonly getters in forms (#19188)
PR Close #19188
This commit is contained in:
+50
-60
@@ -106,9 +106,6 @@ function isOptionsObj(
|
||||
* @stable
|
||||
*/
|
||||
export abstract class AbstractControl {
|
||||
/** @internal */
|
||||
_value: any;
|
||||
|
||||
/** @internal */
|
||||
_pendingDirty: boolean;
|
||||
|
||||
@@ -121,22 +118,12 @@ export abstract class AbstractControl {
|
||||
/** @internal */
|
||||
_updateOn: FormHooks;
|
||||
|
||||
private _valueChanges: EventEmitter<any>;
|
||||
private _statusChanges: EventEmitter<any>;
|
||||
private _status: string;
|
||||
private _errors: ValidationErrors|null;
|
||||
private _pristine: boolean = true;
|
||||
private _touched: boolean = false;
|
||||
private _parent: FormGroup|FormArray;
|
||||
private _asyncValidationSubscription: any;
|
||||
public readonly value: any;
|
||||
|
||||
constructor(public validator: ValidatorFn|null, public asyncValidator: AsyncValidatorFn|null) {}
|
||||
|
||||
/**
|
||||
* The value of the control.
|
||||
*/
|
||||
get value(): any { return this._value; }
|
||||
|
||||
/**
|
||||
* The parent control.
|
||||
*/
|
||||
@@ -154,7 +141,7 @@ export abstract class AbstractControl {
|
||||
* These statuses are mutually exclusive, so a control cannot be
|
||||
* both valid AND invalid or invalid AND disabled.
|
||||
*/
|
||||
get status(): string { return this._status; }
|
||||
public readonly status: string;
|
||||
|
||||
/**
|
||||
* A control is `valid` when its `status === VALID`.
|
||||
@@ -162,7 +149,7 @@ export abstract class AbstractControl {
|
||||
* In order to have this status, the control must have passed all its
|
||||
* validation checks.
|
||||
*/
|
||||
get valid(): boolean { return this._status === VALID; }
|
||||
get valid(): boolean { return this.status === VALID; }
|
||||
|
||||
/**
|
||||
* A control is `invalid` when its `status === INVALID`.
|
||||
@@ -170,7 +157,7 @@ export abstract class AbstractControl {
|
||||
* In order to have this status, the control must have failed
|
||||
* at least one of its validation checks.
|
||||
*/
|
||||
get invalid(): boolean { return this._status === INVALID; }
|
||||
get invalid(): boolean { return this.status === INVALID; }
|
||||
|
||||
/**
|
||||
* A control is `pending` when its `status === PENDING`.
|
||||
@@ -178,7 +165,7 @@ export abstract class AbstractControl {
|
||||
* In order to have this status, the control must be in the
|
||||
* middle of conducting a validation check.
|
||||
*/
|
||||
get pending(): boolean { return this._status == PENDING; }
|
||||
get pending(): boolean { return this.status == PENDING; }
|
||||
|
||||
/**
|
||||
* A control is `disabled` when its `status === DISABLED`.
|
||||
@@ -187,7 +174,7 @@ export abstract class AbstractControl {
|
||||
* are not included in the aggregate value of their ancestor
|
||||
* controls.
|
||||
*/
|
||||
get disabled(): boolean { return this._status === DISABLED; }
|
||||
get disabled(): boolean { return this.status === DISABLED; }
|
||||
|
||||
/**
|
||||
* A control is `enabled` as long as its `status !== DISABLED`.
|
||||
@@ -195,13 +182,13 @@ export abstract class AbstractControl {
|
||||
* In other words, it has a status of `VALID`, `INVALID`, or
|
||||
* `PENDING`.
|
||||
*/
|
||||
get enabled(): boolean { return this._status !== DISABLED; }
|
||||
get enabled(): boolean { return this.status !== DISABLED; }
|
||||
|
||||
/**
|
||||
* Returns any errors generated by failing validation. If there
|
||||
* are no errors, it will return null.
|
||||
*/
|
||||
get errors(): ValidationErrors|null { return this._errors; }
|
||||
public readonly errors: ValidationErrors|null;
|
||||
|
||||
/**
|
||||
* A control is `pristine` if the user has not yet changed
|
||||
@@ -210,7 +197,7 @@ export abstract class AbstractControl {
|
||||
* Note that programmatic changes to a control's value will
|
||||
* *not* mark it dirty.
|
||||
*/
|
||||
get pristine(): boolean { return this._pristine; }
|
||||
public readonly pristine: boolean = true;
|
||||
|
||||
/**
|
||||
* A control is `dirty` if the user has changed the value
|
||||
@@ -225,25 +212,25 @@ export abstract class AbstractControl {
|
||||
* A control is marked `touched` once the user has triggered
|
||||
* a `blur` event on it.
|
||||
*/
|
||||
get touched(): boolean { return this._touched; }
|
||||
public readonly touched: boolean = false;
|
||||
|
||||
/**
|
||||
* A control is `untouched` if the user has not yet triggered
|
||||
* a `blur` event on it.
|
||||
*/
|
||||
get untouched(): boolean { return !this._touched; }
|
||||
get untouched(): boolean { return !this.touched; }
|
||||
|
||||
/**
|
||||
* Emits an event every time the value of the control changes, in
|
||||
* the UI or programmatically.
|
||||
*/
|
||||
get valueChanges(): Observable<any> { return this._valueChanges; }
|
||||
public readonly valueChanges: Observable<any>;
|
||||
|
||||
/**
|
||||
* Emits an event every time the validation status of the control
|
||||
* is re-calculated.
|
||||
*/
|
||||
get statusChanges(): Observable<any> { return this._statusChanges; }
|
||||
public readonly statusChanges: Observable<any>;
|
||||
|
||||
/**
|
||||
* Returns the update strategy of the `AbstractControl` (i.e.
|
||||
@@ -287,7 +274,7 @@ export abstract class AbstractControl {
|
||||
* the model.
|
||||
*/
|
||||
markAsTouched(opts: {onlySelf?: boolean} = {}): void {
|
||||
this._touched = true;
|
||||
(this as{touched: boolean}).touched = true;
|
||||
|
||||
if (this._parent && !opts.onlySelf) {
|
||||
this._parent.markAsTouched(opts);
|
||||
@@ -302,7 +289,7 @@ export abstract class AbstractControl {
|
||||
* controls.
|
||||
*/
|
||||
markAsUntouched(opts: {onlySelf?: boolean} = {}): void {
|
||||
this._touched = false;
|
||||
(this as{touched: boolean}).touched = false;
|
||||
this._pendingTouched = false;
|
||||
|
||||
this._forEachChild(
|
||||
@@ -320,7 +307,7 @@ export abstract class AbstractControl {
|
||||
* the model.
|
||||
*/
|
||||
markAsDirty(opts: {onlySelf?: boolean} = {}): void {
|
||||
this._pristine = false;
|
||||
(this as{pristine: boolean}).pristine = false;
|
||||
|
||||
if (this._parent && !opts.onlySelf) {
|
||||
this._parent.markAsDirty(opts);
|
||||
@@ -335,7 +322,7 @@ export abstract class AbstractControl {
|
||||
* controls.
|
||||
*/
|
||||
markAsPristine(opts: {onlySelf?: boolean} = {}): void {
|
||||
this._pristine = true;
|
||||
(this as{pristine: boolean}).pristine = true;
|
||||
this._pendingDirty = false;
|
||||
|
||||
this._forEachChild((control: AbstractControl) => { control.markAsPristine({onlySelf: true}); });
|
||||
@@ -349,7 +336,7 @@ export abstract class AbstractControl {
|
||||
* Marks the control as `pending`.
|
||||
*/
|
||||
markAsPending(opts: {onlySelf?: boolean} = {}): void {
|
||||
this._status = PENDING;
|
||||
(this as{status: string}).status = PENDING;
|
||||
|
||||
if (this._parent && !opts.onlySelf) {
|
||||
this._parent.markAsPending(opts);
|
||||
@@ -363,14 +350,14 @@ export abstract class AbstractControl {
|
||||
* If the control has children, all children will be disabled to maintain the model.
|
||||
*/
|
||||
disable(opts: {onlySelf?: boolean, emitEvent?: boolean} = {}): void {
|
||||
this._status = DISABLED;
|
||||
this._errors = null;
|
||||
(this as{status: string}).status = DISABLED;
|
||||
(this as{errors: ValidationErrors | null}).errors = null;
|
||||
this._forEachChild((control: AbstractControl) => { control.disable({onlySelf: true}); });
|
||||
this._updateValue();
|
||||
|
||||
if (opts.emitEvent !== false) {
|
||||
this._valueChanges.emit(this._value);
|
||||
this._statusChanges.emit(this._status);
|
||||
(this.valueChanges as EventEmitter<any>).emit(this.value);
|
||||
(this.statusChanges as EventEmitter<string>).emit(this.status);
|
||||
}
|
||||
|
||||
this._updateAncestors(!!opts.onlySelf);
|
||||
@@ -385,7 +372,7 @@ export abstract class AbstractControl {
|
||||
* If the control has children, all children will be enabled.
|
||||
*/
|
||||
enable(opts: {onlySelf?: boolean, emitEvent?: boolean} = {}): void {
|
||||
this._status = VALID;
|
||||
(this as{status: string}).status = VALID;
|
||||
this._forEachChild((control: AbstractControl) => { control.enable({onlySelf: true}); });
|
||||
this.updateValueAndValidity({onlySelf: true, emitEvent: opts.emitEvent});
|
||||
|
||||
@@ -429,17 +416,17 @@ export abstract class AbstractControl {
|
||||
|
||||
if (this.enabled) {
|
||||
this._cancelExistingSubscription();
|
||||
this._errors = this._runValidator();
|
||||
this._status = this._calculateStatus();
|
||||
(this as{errors: ValidationErrors | null}).errors = this._runValidator();
|
||||
(this as{status: string}).status = this._calculateStatus();
|
||||
|
||||
if (this._status === VALID || this._status === PENDING) {
|
||||
if (this.status === VALID || this.status === PENDING) {
|
||||
this._runAsyncValidator(opts.emitEvent);
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.emitEvent !== false) {
|
||||
this._valueChanges.emit(this._value);
|
||||
this._statusChanges.emit(this._status);
|
||||
(this.valueChanges as EventEmitter<any>).emit(this.value);
|
||||
(this.statusChanges as EventEmitter<string>).emit(this.status);
|
||||
}
|
||||
|
||||
if (this._parent && !opts.onlySelf) {
|
||||
@@ -453,7 +440,9 @@ export abstract class AbstractControl {
|
||||
this.updateValueAndValidity({onlySelf: true, emitEvent: opts.emitEvent});
|
||||
}
|
||||
|
||||
private _setInitialStatus() { this._status = this._allControlsDisabled() ? DISABLED : VALID; }
|
||||
private _setInitialStatus() {
|
||||
(this as{status: string}).status = this._allControlsDisabled() ? DISABLED : VALID;
|
||||
}
|
||||
|
||||
private _runValidator(): ValidationErrors|null {
|
||||
return this.validator ? this.validator(this) : null;
|
||||
@@ -461,7 +450,7 @@ export abstract class AbstractControl {
|
||||
|
||||
private _runAsyncValidator(emitEvent?: boolean): void {
|
||||
if (this.asyncValidator) {
|
||||
this._status = PENDING;
|
||||
(this as{status: string}).status = PENDING;
|
||||
const obs = toObservable(this.asyncValidator(this));
|
||||
this._asyncValidationSubscription =
|
||||
obs.subscribe((errors: ValidationErrors | null) => this.setErrors(errors, {emitEvent}));
|
||||
@@ -498,7 +487,7 @@ export abstract class AbstractControl {
|
||||
* ```
|
||||
*/
|
||||
setErrors(errors: ValidationErrors|null, opts: {emitEvent?: boolean} = {}): void {
|
||||
this._errors = errors;
|
||||
(this as{errors: ValidationErrors | null}).errors = errors;
|
||||
this._updateControlsErrors(opts.emitEvent !== false);
|
||||
}
|
||||
|
||||
@@ -525,7 +514,7 @@ export abstract class AbstractControl {
|
||||
*/
|
||||
getError(errorCode: string, path?: string[]): any {
|
||||
const control = path ? this.get(path) : this;
|
||||
return control && control._errors ? control._errors[errorCode] : null;
|
||||
return control && control.errors ? control.errors[errorCode] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -551,10 +540,10 @@ export abstract class AbstractControl {
|
||||
|
||||
/** @internal */
|
||||
_updateControlsErrors(emitEvent: boolean): void {
|
||||
this._status = this._calculateStatus();
|
||||
(this as{status: string}).status = this._calculateStatus();
|
||||
|
||||
if (emitEvent) {
|
||||
this._statusChanges.emit(this._status);
|
||||
(this.statusChanges as EventEmitter<string>).emit(this.status);
|
||||
}
|
||||
|
||||
if (this._parent) {
|
||||
@@ -564,14 +553,14 @@ export abstract class AbstractControl {
|
||||
|
||||
/** @internal */
|
||||
_initObservables() {
|
||||
this._valueChanges = new EventEmitter();
|
||||
this._statusChanges = new EventEmitter();
|
||||
(this as{valueChanges: Observable<any>}).valueChanges = new EventEmitter();
|
||||
(this as{statusChanges: Observable<any>}).statusChanges = new EventEmitter();
|
||||
}
|
||||
|
||||
|
||||
private _calculateStatus(): string {
|
||||
if (this._allControlsDisabled()) return DISABLED;
|
||||
if (this._errors) return INVALID;
|
||||
if (this.errors) return INVALID;
|
||||
if (this._anyControlsHaveStatus(PENDING)) return PENDING;
|
||||
if (this._anyControlsHaveStatus(INVALID)) return INVALID;
|
||||
return VALID;
|
||||
@@ -609,7 +598,7 @@ export abstract class AbstractControl {
|
||||
|
||||
/** @internal */
|
||||
_updatePristine(opts: {onlySelf?: boolean} = {}): void {
|
||||
this._pristine = !this._anyControlsDirty();
|
||||
(this as{pristine: boolean}).pristine = !this._anyControlsDirty();
|
||||
|
||||
if (this._parent && !opts.onlySelf) {
|
||||
this._parent._updatePristine(opts);
|
||||
@@ -618,7 +607,7 @@ export abstract class AbstractControl {
|
||||
|
||||
/** @internal */
|
||||
_updateTouched(opts: {onlySelf?: boolean} = {}): void {
|
||||
this._touched = this._anyControlsTouched();
|
||||
(this as{touched: boolean}).touched = this._anyControlsTouched();
|
||||
|
||||
if (this._parent && !opts.onlySelf) {
|
||||
this._parent._updateTouched(opts);
|
||||
@@ -755,10 +744,10 @@ export class FormControl extends AbstractControl {
|
||||
emitModelToViewChange?: boolean,
|
||||
emitViewToModelChange?: boolean
|
||||
} = {}): void {
|
||||
this._value = this._pendingValue = value;
|
||||
(this as{value: any}).value = this._pendingValue = value;
|
||||
if (this._onChange.length && options.emitModelToViewChange !== false) {
|
||||
this._onChange.forEach(
|
||||
(changeFn) => changeFn(this._value, options.emitViewToModelChange !== false));
|
||||
(changeFn) => changeFn(this.value, options.emitViewToModelChange !== false));
|
||||
}
|
||||
this.updateValueAndValidity(options);
|
||||
}
|
||||
@@ -811,7 +800,7 @@ export class FormControl extends AbstractControl {
|
||||
this._applyFormState(formState);
|
||||
this.markAsPristine(options);
|
||||
this.markAsUntouched(options);
|
||||
this.setValue(this._value, options);
|
||||
this.setValue(this.value, options);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -868,11 +857,11 @@ export class FormControl extends AbstractControl {
|
||||
|
||||
private _applyFormState(formState: any) {
|
||||
if (this._isBoxedValue(formState)) {
|
||||
this._value = this._pendingValue = formState.value;
|
||||
(this as{value: any}).value = this._pendingValue = formState.value;
|
||||
formState.disabled ? this.disable({onlySelf: true, emitEvent: false}) :
|
||||
this.enable({onlySelf: true, emitEvent: false});
|
||||
} else {
|
||||
this._value = this._pendingValue = formState;
|
||||
(this as{value: any}).value = this._pendingValue = formState;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1172,7 +1161,7 @@ export class FormGroup extends AbstractControl {
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
_updateValue(): void { this._value = this._reduceValue(); }
|
||||
_updateValue(): void { (this as{value: any}).value = this._reduceValue(); }
|
||||
|
||||
/** @internal */
|
||||
_anyControls(condition: Function): boolean {
|
||||
@@ -1498,8 +1487,9 @@ export class FormArray extends AbstractControl {
|
||||
|
||||
/** @internal */
|
||||
_updateValue(): void {
|
||||
this._value = this.controls.filter((control) => control.enabled || this.disabled)
|
||||
.map((control) => control.value);
|
||||
(this as{value: any}).value =
|
||||
this.controls.filter((control) => control.enabled || this.disabled)
|
||||
.map((control) => control.value);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
||||
Reference in New Issue
Block a user