You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过原型扩展FormControl功能?实现markAsDirty触发onMarkAsDirty

实现带onMarkAsDirty事件的FormControl

方案1:自定义继承FormControl的类

这种方式更可控,避免全局原型修改带来的潜在副作用:

import { FormControl, ValidatorFn, AsyncValidatorFn } from '@angular/forms';
import { Subject } from 'rxjs';

export class CustomFormControl extends FormControl {
  // 用于发射markAsDirty触发事件的可观察对象
  readonly onMarkAsDirty = new Subject<void>();

  constructor(
    formState?: any,
    validatorOrOpts?: ValidatorFn | ValidatorFn[] | null,
    asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[] | null
  ) {
    super(formState, validatorOrOpts, asyncValidator);
  }

  // 重写markAsDirty方法,触发事件
  markAsDirty(opts?: { onlySelf?: boolean }): void {
    super.markAsDirty(opts);
    this.onMarkAsDirty.next();
  }
}

使用示例

// 创建自定义控件实例
const control = new CustomFormControl('初始值');

// 订阅脏值标记事件
control.onMarkAsDirty.subscribe(() => {
  console.log('控件已被标记为脏值!');
});

// 调用markAsDirty会触发订阅回调
control.markAsDirty();

结合FormBuilder使用:

import { FormBuilder } from '@angular/forms';

// 组件内代码
constructor(private fb: FormBuilder) {
  const form = this.fb.group({
    username: new CustomFormControl('')
  });

  const usernameControl = form.get('username') as CustomFormControl;
  usernameControl.onMarkAsDirty.subscribe(() => {
    console.log('用户名控件变为脏值');
  });
}

方案2:扩展FormControl全局原型

如果需要所有FormControl实例都具备该功能,可以通过扩展原型实现,建议在应用启动时(如app.module.ts的ngOnInit)执行以下代码:

import { FormControl } from '@angular/forms';
import { Subject } from 'rxjs';

// 保存原生markAsDirty方法
const originalMarkAsDirty = FormControl.prototype.markAsDirty;

// 为原型添加懒加载的onMarkAsDirty属性
Object.defineProperty(FormControl.prototype, 'onMarkAsDirty', {
  get() {
    if (!this._onMarkAsDirty) {
      this._onMarkAsDirty = new Subject<void>();
    }
    return this._onMarkAsDirty;
  },
  enumerable: true,
  configurable: true
});

// 重写markAsDirty方法,触发事件
FormControl.prototype.markAsDirty = function(opts?: { onlySelf?: boolean }) {
  originalMarkAsDirty.call(this, opts);
  this._onMarkAsDirty?.next();
};

使用示例

所有FormControl实例(包括FormBuilder创建的)都会自动拥有onMarkAsDirty属性:

import { FormBuilder } from '@angular/forms';

constructor(private fb: FormBuilder) {
  const form = this.fb.group({
    email: ['']
  });

  const emailControl = form.get('email') as FormControl;
  emailControl.onMarkAsDirty.subscribe(() => {
    console.log('邮箱控件被标记为脏值');
  });

  emailControl.markAsDirty(); // 触发订阅回调
}

TypeScript类型补充

为避免类型报错,可在项目的typings.d.ts中添加类型扩展:

import { Subject } from 'rxjs';

declare module '@angular/forms' {
  interface FormControl {
    _onMarkAsDirty?: Subject<void>;
    onMarkAsDirty: Subject<void>;
  }
}

内容的提问来源于stack exchange,提问作者Anton Minchenko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 03:10:25