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

Angular:如何手动将验证器标记为dirty状态

问题解决思路

你的问题核心在于:自定义货币组件内部维护了独立的currencyGroup表单组,它和Formly提供的formControl是两个完全独立的FormControl实例。你在步进器里调用markAsTouched()标记的是Formly绑定的控件状态,但组件模板里判断的却是内部currencyForm的状态,所以外部控件状态更新无法同步到模板,自然不会显示预期的错误样式。

方案一:复用Formly的formControl(推荐)

直接移除组件内部的独立表单组,复用Formly自带的formControl管理状态,这样外部的状态更新能直接同步到模板:

修改currency.component.ts:

import { Component, OnInit } from '@angular/core';
import { CurrencyPipe} from '@angular/common';
import { FieldType } from '@ngx-formly/core';
import { Validators } from '@angular/forms';

@Component({
  selector: 'app-formly-field-currency',
  templateUrl: './currency.component.html'
})
export class FormlyFieldCurrencyComponent extends FieldType implements OnInit {

  constructor(private currencyPipe: CurrencyPipe) {
    super();
  }

  ngOnInit(): void {
    // 为Formly自带的formControl添加验证规则
    this.formControl.setValidators([Validators.required]);
    this.formControl.updateValueAndValidity();
  }

  get currencyAmount(){
    return this.formControl;
  }
}

修改currency.component.html:

<div class="input-group mb-3">
  <div class="input-group mt-2 flex-nowrap">      
    <div class="input-group-prepend">
      <span class="input-group-text">$</span>
    </div>
    <input  matInput
            [class.is-invalid] = "formControl.invalid && formControl.touched"
            type="number" 
            class="form-control"
            [formControl]="formControl"
            [formlyAttributes]="field"
    > 
  </div>      
  <div 
    class="mx-auto"
    *ngIf="(formControl.invalid && formControl.touched) || formControl.dirty">
    <small *ngIf="formControl.errors?.required" class="text-danger">
        Currency amount is required.
    </small>
  </div>
</div> 

修改后,步进器中调用markAsTouched()时,就能直接触发组件的错误样式。

方案二:同步内部控件与Formly控件的状态

如果必须保留内部的currencyGroup,可以通过以下两种方式同步状态:

方式1:组件内监听状态变化

在currency.component.ts中添加状态监听,同步Formly控件与内部控件的状态:

import { OnInit } from '@angular/core';

// ... 其他代码

ngOnInit(): void {
  // 监听外部控件状态变化,同步到内部控件
  this.formControl.statusChanges.subscribe(() => {
    if (this.formControl.touched) {
      this.currencyAmount.markAsTouched();
    }
    if (this.formControl.dirty) {
      this.currencyAmount.markAsDirty();
    }
  });
}

方式2:步进器中直接操作内部控件

修改stepper.component.ts的displayValidation方法,通过字段的componentInstance获取组件实例,直接标记内部控件:

displayValidation(field: FormlyFieldConfig) {
  if (field?.fieldGroup){
    field.fieldGroup.forEach((curFieldGroup) => {
      curFieldGroup.formControl.markAsTouched();
      this.setFieldTypeInvalid(curFieldGroup.type, curFieldGroup.formControl.status);

      // 针对自定义货币组件,标记内部控件状态
      if (curFieldGroup.type === 'currency') {
        const currencyComp = curFieldGroup.componentInstance as FormlyFieldCurrencyComponent;
        currencyComp.currencyAmount.markAsTouched();
        currencyComp.currencyAmount.markAsDirty();
      }
    });
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 08:10:23