Repository: angular/angular
File: packages/forms/src/model/abstract_model.ts (TypeScript)

Code before:
   * * `emitEvent`: When true or not supplied (the default), the `statusChanges`,
   * `valueChanges` and `events`
   * observables emit events with the latest status and value when the control is enabled.
   * When false, no events are emitted.
   */
  enable(opts: {onlySelf?: boolean; emitEvent?: boolean} = {}): void {
    // If parent has been marked artificially dirty we don't want to re-calculate the
    // parent's dirtiness based on the children.
    const skipPristineCheck = this._parentMarkedDirty(opts.onlySelf);

    this.status = VALID;
    this._forEachChild((control: AbstractControl) => {
      control.enable({...opts, onlySelf: true});
    });
    this.updateValueAndValidity({onlySelf: true, emitEvent: opts.emitEvent});

    this._updateAncestors({...opts, skipPristineCheck}, this);
    this._onDisabledChange.forEach((changeFn) => changeFn(false));
  }

  private _updateAncestors(
    opts: {onlySelf?: boolean; emitEvent?: boolean; skipPristineCheck?: boolean},
    sourceControl: AbstractControl,
  ): void {
    if (!opts.onlySelf) {
      this._parent?.updateValueAndValidity?.(opts);
      if (!opts.skipPristineCheck) {
        this._parent?._updatePristine?.({}, sourceControl);
      }
      this._parent?._updateTouched?.({}, sourceControl);
    }
  }

  /**
   * Sets the parent of the control
   *
   * @param parent The new parent.
   */
  setParent(parent: FormGroup | FormArray | null): void {
    this._parent = parent;
  }

  /**
   * Sets the value of the control. Abstract method (implemented in sub-classes).
   */
  abstract setValue(value: TRawValue, options?: Object): void;

  /**
   * Patches the value of the control. Abstract method (implemented in sub-classes).
   */
  abstract patchValue(value: TValue, options?: Object): void;

Review comment (suggestion):
In regular TS, that second optional chaining isn't necessary. 
```suggestion
      this._parent?.updateValueAndValidity(opts);
```

Code after:
   * * `emitEvent`: When true or not supplied (the default), the `statusChanges`,
   * `valueChanges` and `events`
   * observables emit events with the latest status and value when the control is enabled.
   * When false, no events are emitted.
   */
  enable(opts: {onlySelf?: boolean; emitEvent?: boolean} = {}): void {
    // If parent has been marked artificially dirty we don't want to re-calculate the
    // parent's dirtiness based on the children.
    const skipPristineCheck = this._parentMarkedDirty(opts.onlySelf);

    this.status = VALID;
    this._forEachChild((control: AbstractControl) => {
      control.enable({...opts, onlySelf: true});
    });
    this.updateValueAndValidity({onlySelf: true, emitEvent: opts.emitEvent});

    this._updateAncestors({...opts, skipPristineCheck}, this);
    this._onDisabledChange.forEach((changeFn) => changeFn(false));
  }

  private _updateAncestors(
    opts: {onlySelf?: boolean; emitEvent?: boolean; skipPristineCheck?: boolean},
    sourceControl: AbstractControl,
  ): void {
    if (!opts.onlySelf) {
      this._parent?.updateValueAndValidity(opts);
      if (!opts.skipPristineCheck) {
        this._parent?._updatePristine({}, sourceControl);
      }
      this._parent?._updateTouched({}, sourceControl);
    }
  }

  /**
   * Sets the parent of the control
   *
   * @param parent The new parent.
   */
  setParent(parent: FormGroup | FormArray | null): void {
    this._parent = parent;
  }

  /**
   * Sets the value of the control. Abstract method (implemented in sub-classes).
   */
  abstract setValue(value: TRawValue, options?: Object): void;

  /**
   * Patches the value of the control. Abstract method (implemented in sub-classes).
   */
  abstract patchValue(value: TValue, options?: Object): void;