如何在Angular 6中当ngModelGroup无效时设置mat-form-field为无效?
解决Angular 6 + Angular Material 2中ngModelGroup无效时同步mat-form-field状态的问题
好的,我来帮你搞定这个问题。你的自定义password-matcher验证器已经能把passGroup设为无效状态,但mat-form-field默认只会关联内部input对应的FormControl状态,所以不会自动跟着组的状态变无效。这里有两种靠谱的解决方案:
方法一:修改自定义验证器,同步错误到子控件
这是最贴合Angular表单设计的方式,我们让验证器不仅给ngModelGroup设置错误,同时把错误标记添加到组内的两个密码控件上,这样mat-form-field就能自动识别并显示无效状态。
修改你的password-matcher指令代码如下:
import { Directive, forwardRef } from '@angular/core'; import { Validator, AbstractControl, NG_VALIDATORS } from '@angular/forms'; @Directive({ selector: '[password-matcher]', providers: [ { provide: NG_VALIDATORS, useExisting: forwardRef(() => PasswordMatcherDirective), multi: true } ] }) export class PasswordMatcherDirective implements Validator { validate(control: AbstractControl): { [key: string]: any } | null { // 获取组内的两个密码控件 const passwordCtrl = control.get('password'); const repeatPwdCtrl = control.get('repeatPassword'); // 如果控件不存在,直接返回 if (!passwordCtrl || !repeatPwdCtrl) return null; // 检查密码是否匹配 if (passwordCtrl.value !== repeatPwdCtrl.value) { // 给组设置错误 control.setErrors({ passwordMismatch: '两次输入的密码不匹配' }); // 给子控件添加错误(保留原有错误,比如必填、最小长度) passwordCtrl.setErrors({ ...passwordCtrl.errors, passwordMismatch: true }); repeatPwdCtrl.setErrors({ ...repeatPwdCtrl.errors, passwordMismatch: true }); } else { // 密码匹配时清除错误(注意保留其他可能的错误) if (control.hasError('passwordMismatch')) { control.setErrors(null); } // 清除子控件的密码不匹配错误 if (passwordCtrl.hasError('passwordMismatch')) { delete passwordCtrl.errors?.passwordMismatch; passwordCtrl.updateValueAndValidity(); } if (repeatPwdCtrl.hasError('passwordMismatch')) { delete repeatPwdCtrl.errors?.passwordMismatch; repeatPwdCtrl.updateValueAndValidity(); } } return control.errors; } }
这样修改后,当两次密码不匹配时,两个mat-form-field都会自动呈现无效状态(红色边框、错误提示等),完全符合Material组件的默认行为。
方法二:模板绑定直接控制mat-form-field状态
如果你不想修改验证器代码,也可以直接在模板里通过ngClass绑定Angular Material的无效样式类,手动控制mat-form-field的状态。
修改你的模板代码:
<div ngModelGroup="passGroup" password-matcher #passGroup="ngModelGroup"> <div class="formGroup"> <mat-form-field [ngClass]="{'mat-form-field-invalid': passGroup.invalid && reg.password}" > <input matInput type="password" class='inputs' [(ngModel)]='reg.password' name='password' required minlength="8" (input)='onChangeReg(reg)' > <!-- 显示错误提示 --> <mat-error *ngIf="passGroup.invalid">两次输入的密码不匹配</mat-error> </mat-form-field> </div> <div class="formGroup"> <mat-form-field class="example-full-width" [ngClass]="{'mat-form-field-invalid': passGroup.invalid && reg.repeatPassword}" > <input matInput type="password" class='inputs' [(ngModel)]='reg.repeatPassword' name='repeatPassword' required minlength="8" (input)='onChangeReg(reg)' > <mat-error *ngIf="passGroup.invalid">两次输入的密码不匹配</mat-error> </mat-form-field> </div> </div>
这里我们通过[ngClass]给mat-form-field添加mat-form-field-invalid类,条件是passGroup无效且对应的输入框已有内容(避免页面加载时就显示错误)。同时用mat-error组件显示统一的错误提示。
两种方法各有优势:方法一更规范,能让表单状态在Angular的表单体系内统一管理;方法二更灵活,适合快速调整样式逻辑,不需要修改验证器代码。你可以根据自己的需求选择~
内容的提问来源于stack exchange,提问作者MoJlo4HuK
相关产品推荐
相关产品推荐

