mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
refactor(forms): use optional chaining for safer method calls in form directives
Simplifies null checks by leveraging optional chaining when invoking optional callbacks
This commit is contained in:
committed by
Andrew Kushnir
parent
e7fa177923
commit
8b3b069be7
@@ -264,7 +264,7 @@ export abstract class AbstractControlDirective {
|
||||
* Resets the control with the provided value if the control is present.
|
||||
*/
|
||||
reset(value: any = undefined): void {
|
||||
if (this.control) this.control.reset(value);
|
||||
this.control?.reset(value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -41,10 +41,8 @@ export class AbstractFormGroupDirective extends ControlContainer implements OnIn
|
||||
|
||||
/** @docs-private */
|
||||
ngOnDestroy(): void {
|
||||
if (this.formDirective) {
|
||||
// Remove the group from its parent group.
|
||||
this.formDirective.removeFormGroup(this);
|
||||
}
|
||||
// Remove the group from its parent group.
|
||||
this.formDirective?.removeFormGroup(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -256,9 +256,9 @@ export class NgForm extends ControlContainer implements Form, AfterViewInit {
|
||||
removeControl(dir: NgModel): void {
|
||||
resolvedPromise.then(() => {
|
||||
const container = this._findContainer(dir.path);
|
||||
if (container) {
|
||||
container.removeControl(dir.name);
|
||||
}
|
||||
|
||||
container?.removeControl(dir.name);
|
||||
|
||||
this._directives.delete(dir);
|
||||
});
|
||||
}
|
||||
@@ -288,9 +288,7 @@ export class NgForm extends ControlContainer implements Form, AfterViewInit {
|
||||
removeFormGroup(dir: NgModelGroup): void {
|
||||
resolvedPromise.then(() => {
|
||||
const container = this._findContainer(dir.path);
|
||||
if (container) {
|
||||
container.removeControl(dir.name);
|
||||
}
|
||||
container?.removeControl?.(dir.name);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -278,7 +278,7 @@ export class NgModel extends NgControl implements OnChanges, OnDestroy {
|
||||
|
||||
/** @docs-private */
|
||||
ngOnDestroy(): void {
|
||||
this.formDirective && this.formDirective.removeControl(this);
|
||||
this.formDirective?.removeControl(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -357,24 +357,20 @@ export abstract class AbstractFormDirective
|
||||
}
|
||||
|
||||
private _cleanUpFormContainer(dir: FormArrayName | FormGroupName): void {
|
||||
if (this.form) {
|
||||
const ctrl: any = this.form.get(dir.path);
|
||||
if (ctrl) {
|
||||
const isControlUpdated = cleanUpFormContainer(ctrl, dir);
|
||||
if (isControlUpdated) {
|
||||
// Run validity check only in case a control was updated (i.e. view validators were
|
||||
// removed) as removing view validators might cause validity to change.
|
||||
ctrl.updateValueAndValidity({emitEvent: false});
|
||||
}
|
||||
const ctrl: any = this.form?.get(dir.path);
|
||||
if (ctrl) {
|
||||
const isControlUpdated = cleanUpFormContainer(ctrl, dir);
|
||||
if (isControlUpdated) {
|
||||
// Run validity check only in case a control was updated (i.e. view validators were
|
||||
// removed) as removing view validators might cause validity to change.
|
||||
ctrl.updateValueAndValidity({emitEvent: false});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _updateRegistrations() {
|
||||
this.form._registerOnCollectionChange(this._onCollectionChange);
|
||||
if (this._oldForm) {
|
||||
this._oldForm._registerOnCollectionChange(() => {});
|
||||
}
|
||||
this._oldForm?._registerOnCollectionChange(() => {});
|
||||
}
|
||||
|
||||
private _updateValidators() {
|
||||
|
||||
@@ -179,9 +179,7 @@ export class FormControlName extends NgControl implements OnChanges, OnDestroy {
|
||||
|
||||
/** @docs-private */
|
||||
ngOnDestroy(): void {
|
||||
if (this.formDirective) {
|
||||
this.formDirective.removeControl(this);
|
||||
}
|
||||
this.formDirective?.removeControl(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -286,7 +286,7 @@ export class NgSelectOption implements OnDestroy {
|
||||
@Input('value')
|
||||
set value(value: any) {
|
||||
this._setElementValue(value);
|
||||
if (this._select) this._select._writeValueAfterRender();
|
||||
this._select?._writeValueAfterRender();
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -296,9 +296,7 @@ export class NgSelectOption implements OnDestroy {
|
||||
|
||||
/** @docs-private */
|
||||
ngOnDestroy(): void {
|
||||
if (this._select) {
|
||||
this._select._optionMap.delete(this.id);
|
||||
this._select._writeValueAfterRender();
|
||||
}
|
||||
this._select?._optionMap.delete(this.id);
|
||||
this._select?._writeValueAfterRender();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,10 +120,9 @@ export function cleanUpControl(
|
||||
// case. We still check the presence of `valueAccessor` before invoking its methods to make sure
|
||||
// that cleanup works correctly if app code or tests are setup to ignore the error thrown from
|
||||
// `selectValueAccessor`. See https://github.com/angular/angular/issues/40521.
|
||||
if (dir.valueAccessor) {
|
||||
dir.valueAccessor.registerOnChange(noop);
|
||||
dir.valueAccessor.registerOnTouched(noop);
|
||||
}
|
||||
|
||||
dir?.valueAccessor?.registerOnChange(noop);
|
||||
dir?.valueAccessor?.registerOnTouched(noop);
|
||||
|
||||
cleanUpValidators(control, dir);
|
||||
|
||||
|
||||
@@ -162,9 +162,7 @@ abstract class AbstractValidatorDirective implements Validator, OnChanges {
|
||||
const input = this.normalizeInput(changes[this.inputName].currentValue);
|
||||
this._enabled = this.enabled(input);
|
||||
this._validator = this._enabled ? this.createValidator(input) : nullValidator;
|
||||
if (this._onChange) {
|
||||
this._onChange();
|
||||
}
|
||||
this._onChange?.();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -997,8 +997,8 @@ export abstract class AbstractControl<
|
||||
this.touched = true;
|
||||
|
||||
const sourceControl = opts.sourceControl ?? this;
|
||||
if (this._parent && !opts.onlySelf) {
|
||||
this._parent.markAsTouched({...opts, sourceControl});
|
||||
if (!opts.onlySelf) {
|
||||
this._parent?.markAsTouched({...opts, sourceControl});
|
||||
}
|
||||
|
||||
if (changed && opts.emitEvent !== false) {
|
||||
@@ -1087,8 +1087,8 @@ export abstract class AbstractControl<
|
||||
control.markAsUntouched({onlySelf: true, emitEvent: opts.emitEvent, sourceControl});
|
||||
});
|
||||
|
||||
if (this._parent && !opts.onlySelf) {
|
||||
this._parent._updateTouched(opts, sourceControl);
|
||||
if (!opts.onlySelf) {
|
||||
this._parent?._updateTouched(opts, sourceControl);
|
||||
}
|
||||
|
||||
if (changed && opts.emitEvent !== false) {
|
||||
@@ -1131,8 +1131,8 @@ export abstract class AbstractControl<
|
||||
this.pristine = false;
|
||||
|
||||
const sourceControl = opts.sourceControl ?? this;
|
||||
if (this._parent && !opts.onlySelf) {
|
||||
this._parent.markAsDirty({...opts, sourceControl});
|
||||
if (!opts.onlySelf) {
|
||||
this._parent?.markAsDirty({...opts, sourceControl});
|
||||
}
|
||||
|
||||
if (changed && opts.emitEvent !== false) {
|
||||
@@ -1184,8 +1184,8 @@ export abstract class AbstractControl<
|
||||
control.markAsPristine({onlySelf: true, emitEvent: opts.emitEvent});
|
||||
});
|
||||
|
||||
if (this._parent && !opts.onlySelf) {
|
||||
this._parent._updatePristine(opts, sourceControl);
|
||||
if (!opts.onlySelf) {
|
||||
this._parent?._updatePristine(opts, sourceControl);
|
||||
}
|
||||
|
||||
if (changed && opts.emitEvent !== false) {
|
||||
@@ -1230,8 +1230,8 @@ export abstract class AbstractControl<
|
||||
(this.statusChanges as EventEmitter<FormControlStatus>).emit(this.status);
|
||||
}
|
||||
|
||||
if (this._parent && !opts.onlySelf) {
|
||||
this._parent.markAsPending({...opts, sourceControl});
|
||||
if (!opts.onlySelf) {
|
||||
this._parent?.markAsPending({...opts, sourceControl});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1321,12 +1321,12 @@ export abstract class AbstractControl<
|
||||
opts: {onlySelf?: boolean; emitEvent?: boolean; skipPristineCheck?: boolean},
|
||||
sourceControl: AbstractControl,
|
||||
): void {
|
||||
if (this._parent && !opts.onlySelf) {
|
||||
this._parent.updateValueAndValidity(opts);
|
||||
if (!opts.onlySelf) {
|
||||
this._parent?.updateValueAndValidity(opts);
|
||||
if (!opts.skipPristineCheck) {
|
||||
this._parent._updatePristine({}, sourceControl);
|
||||
this._parent?._updatePristine({}, sourceControl);
|
||||
}
|
||||
this._parent._updateTouched({}, sourceControl);
|
||||
this._parent?._updateTouched({}, sourceControl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1415,8 +1415,8 @@ export abstract class AbstractControl<
|
||||
(this.statusChanges as EventEmitter<FormControlStatus>).emit(this.status);
|
||||
}
|
||||
|
||||
if (this._parent && !opts.onlySelf) {
|
||||
this._parent.updateValueAndValidity({...opts, sourceControl});
|
||||
if (!opts.onlySelf) {
|
||||
this._parent?.updateValueAndValidity({...opts, sourceControl});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1604,7 +1604,7 @@ export abstract class AbstractControl<
|
||||
*/
|
||||
getError(errorCode: string, path?: Array<string | number> | string): any {
|
||||
const control = path ? this.get(path) : this;
|
||||
return control && control.errors ? control.errors[errorCode] : null;
|
||||
return control?.errors ? control.errors[errorCode] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1729,8 +1729,8 @@ export abstract class AbstractControl<
|
||||
const changed = this.pristine !== newPristine;
|
||||
this.pristine = newPristine;
|
||||
|
||||
if (this._parent && !opts.onlySelf) {
|
||||
this._parent._updatePristine(opts, changedControl);
|
||||
if (!opts.onlySelf) {
|
||||
this._parent?._updatePristine(opts, changedControl);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
@@ -1743,8 +1743,8 @@ export abstract class AbstractControl<
|
||||
this.touched = this._anyControlsTouched();
|
||||
this._events.next(new TouchedChangeEvent(this.touched, changedControl));
|
||||
|
||||
if (this._parent && !opts.onlySelf) {
|
||||
this._parent._updateTouched(opts, changedControl);
|
||||
if (!opts.onlySelf) {
|
||||
this._parent?._updateTouched(opts, changedControl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1768,8 +1768,7 @@ export abstract class AbstractControl<
|
||||
* @internal
|
||||
*/
|
||||
private _parentMarkedDirty(onlySelf?: boolean): boolean {
|
||||
const parentDirty = this._parent && this._parent.dirty;
|
||||
return !onlySelf && !!parentDirty && !this._parent!._anyControlsDirty();
|
||||
return !onlySelf && !!this._parent?.dirty && !this._parent!._anyControlsDirty();
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
||||
Reference in New Issue
Block a user