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
相关产品推荐
相关产品推荐

