Angular 7模板驱动表单两输入字段值比较验证问题求助
解决Angular 7模板驱动表单的字段比较验证问题
我刚接触Angular的时候也碰到过类似的场景,模板驱动表单的自定义验证确实需要结合控件状态来处理,光在组件里判断值没法自动关联到表单的错误状态,所以用户看不到提示。下面给你两种可行的方案,你可以根据需求选择:
方案一:自定义验证指令(推荐,符合模板驱动表单最佳实践)
这种方式可以把验证逻辑封装成指令,复用性更强,而且能自动关联表单的错误状态。
1. 创建比较验证指令
在项目中新建一个指令文件(比如compare-values.directive.ts),实现表单验证逻辑:
import { Directive, Input } from '@angular/core'; import { NG_VALIDATORS, Validator, FormGroup, ValidationErrors } from '@angular/forms'; @Directive({ selector: '[appCompareValues]', providers: [{ provide: NG_VALIDATORS, useExisting: CompareValuesDirective, multi: true }] }) export class CompareValuesDirective implements Validator { // 接收配置:两个控件名和比较操作符 @Input() appCompareValues: { firstControl: string; secondControl: string; operator: '<' | '>' }; validate(formGroup: FormGroup): ValidationErrors | null { if (!this.appCompareValues) return null; const { firstControl, secondControl, operator } = this.appCompareValues; const firstVal = formGroup.get(firstControl)?.value; const secondVal = formGroup.get(secondControl)?.value; // 空值交给required验证处理 if (firstVal == null || secondVal == null) return null; let isValid = false; switch (operator) { case '<': isValid = firstVal < secondVal; break; case '>': isValid = firstVal > secondVal; break; default: isValid = true; } // 返回错误标记,用于模板判断 return isValid ? null : { valueMismatch: true }; } }
2. 在模块中声明指令
打开你的模块文件(比如app.module.ts),导入并声明这个指令:
import { CompareValuesDirective } from './compare-values.directive'; @NgModule({ declarations: [ // ...其他组件 CompareValuesDirective ], // ...其他配置 }) export class AppModule { }
3. 修改模板关联验证并显示错误
在表单上添加指令,同时在对应控件的mat-form-field里添加错误提示:
<div *ngIf="_issueCategory"> <form (submit)="submitIssueThreshold(issueThresholdForm)" #issueThresholdForm="ngForm" <!-- 配置验证:lowScore必须小于highScore --> [appCompareValues]="{ firstControl: 'lowScore', secondControl: 'highScore', operator: '<' }" > <mat-form-field class="half-width" floatLabel="always"> <mat-label [translate]="'issueThreshold.modals.highScore'"></mat-label> <input name="highScore" type="number" matInput placeholder="0" [(ngModel)]="_issueCategory.highScore" required #highScore="ngModel"> </mat-form-field> <mat-form-field class="half-width" floatLabel="always"> <mat-label [translate]="'issueThreshold.modals.lowScore'"></mat-label> <input name="lowScore" type="number" matInput placeholder="0" [(ngModel)]="_issueCategory.lowScore" required #lowScore="ngModel"> <!-- 显示比较错误 --> <mat-error *ngIf="issueThresholdForm.hasError('valueMismatch')"> {{ 'issueThreshold.modals.lowScoreMustBeLessThanHigh' | translate }} </mat-error> </mat-form-field> <!-- 其他表单内容不变 --> <mat-form-field class="full-width" floatLabel="always"> <mat-label [translate]="'issueThreshold.modals.description'"></mat-label> <textarea name="description" matInput [(ngModel)]="_issueCategory.thresholdDescription"> </textarea> </mat-form-field> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal" [translate]="'modal-confirm.cancel'"></button> <button type="submit" class="btn btn-primary primary" [disabled]="issueThresholdForm.invalid || issueThresholdForm.pristine" [translate]="'modal-confirm.submit'"></button> </div> </form> </div>
方案二:组件内手动控制控件错误(快速实现)
如果不想新建指令,可以直接在组件中监听控件变化,手动设置错误状态:
1. 修改组件代码
在组件类中添加以下代码,监听两个输入框的变化并验证:
import { Component, ViewChild, NgModel } from '@angular/core'; import { NgForm } from '@angular/forms'; @Component({ // 组件元数据不变 }) export class YourComponent { @ViewChild('issueThresholdForm') issueThresholdForm: NgForm; @ViewChild('lowScore') lowScoreCtrl: NgModel; @ViewChild('highScore') highScoreCtrl: NgModel; ngAfterViewInit() { // 监听两个控件的值变化,触发验证 this.lowScoreCtrl.control.valueChanges.subscribe(() => this.validateLowHighScore()); this.highScoreCtrl.control.valueChanges.subscribe(() => this.validateLowHighScore()); } validateLowHighScore() { const lowScore = this.issueThresholdForm.value.lowScore; const highScore = this.issueThresholdForm.value.highScore; if (lowScore > highScore) { // 设置lowScore控件的错误 this.lowScoreCtrl.control.setErrors({ greaterThanHigh: true }); } else { // 如果错误存在,移除它 if (this.lowScoreCtrl.control.hasError('greaterThanHigh')) { delete this.lowScoreCtrl.control.errors['greaterThanHigh']; // 如果没有其他错误,清空错误状态 if (Object.keys(this.lowScoreCtrl.control.errors || {}).length === 0) { this.lowScoreCtrl.control.setErrors(null); } } } } submitIssueThreshold(form: NgForm) { // 先触发一次验证 this.validateLowHighScore(); if (form.invalid) return; // 你的提交逻辑 } }
2. 修改模板显示错误
在lowScore的mat-form-field中添加错误提示:
<mat-form-field class="half-width" floatLabel="always"> <mat-label [translate]="'issueThreshold.modals.lowScore'"></mat-label> <input name="lowScore" type="number" matInput placeholder="0" [(ngModel)]="_issueCategory.lowScore" required #lowScore="ngModel"> <mat-error *ngIf="lowScore.hasError('greaterThanHigh')"> {{ 'issueThreshold.modals.lowScoreMustBeLessThanHigh' | translate }} </mat-error> <mat-error *ngIf="lowScore.hasError('required')"> {{ 'common.required' | translate }} </mat-error> </mat-form-field>
两种方案都能实现需求,方案一更适合复用,方案二适合快速迭代。记得在你的国际化文件中添加对应的错误提示文本哦~
内容的提问来源于stack exchange,提问作者user1712638
相关产品推荐
相关产品推荐

