Angular模板驱动表单:为重复mat-input字段添加唯一值验证
嘿,针对你在模板驱动表单里循环生成Angular Material输入框,要实现值不能重复的验证需求,我给你整理了两种可行方案,一步步来就能搞定:
方案一:自定义验证器指令(推荐,可复用)
如果这个重复值验证逻辑以后还要在其他组件用,写个自定义指令是最优解,步骤如下:
1. 生成并编写验证器指令
先通过Angular CLI生成指令:
ng generate directive unique-distance
然后打开生成的unique-distance.directive.ts,替换成下面的代码:
import { Directive, Input } from '@angular/core'; import { Validator, AbstractControl, ValidationErrors } from '@angular/forms'; @Directive({ selector: '[appUniqueDistance]' }) export class UniqueDistanceDirective implements Validator { // 接收整个距离数组 @Input('appUniqueDistance') distanceArray: { distance: number }[] = []; // 接收当前输入框的索引,用来排除自身(避免和自己比较) @Input() currentIndex: number = 0; validate(control: AbstractControl): ValidationErrors | null { const currentValue = control.value; // 空值不触发重复验证,可根据需求调整 if (!currentValue) return null; // 检查数组中除当前项外,是否有相同的距离值 const isDuplicate = this.distanceArray.some((item, index) => { return index !== this.currentIndex && item.distance === currentValue; }); return isDuplicate ? { duplicateDistance: true } : null; } }
2. 在模板中应用指令
修改你现有的模板代码,给每个输入框绑定指令,同时传入数组和当前索引:
<div *ngFor="let distanceVal of distanceArray;let i=index" layout-gt-xs="row"> <div flex="30" flex-offset="15"> <mat-form-field> <input matInput placeholder="Distance" type="number" [(ngModel)]="distanceVal.distance" name="distance{{i}}" appUniqueDistance [distanceArray]="distanceArray" [currentIndex]="i" #distanceInput="ngModel" > <!-- 显示重复错误提示 --> <mat-error *ngIf="distanceInput.invalid && (distanceInput.dirty || distanceInput.touched)"> <span *ngIf="distanceInput.hasError('duplicateDistance')">该距离值已存在,请输入不同的数值</span> </mat-error> </mat-form-field> </div> </div>
这里的#distanceInput="ngModel"是模板引用变量,用来获取输入框的表单状态;mat-error会在输入框被触摸/修改且验证不通过时显示。
3. 在模块中注册指令
最后要把指令添加到对应模块的declarations(和exports,如果要在其他组件复用)里:
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { UniqueDistanceDirective } from './unique-distance.directive'; import { FormsModule } from '@angular/forms'; // 模板驱动表单必须引入 import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; @NgModule({ declarations: [UniqueDistanceDirective], imports: [ CommonModule, FormsModule, MatFormFieldModule, MatInputModule ], exports: [UniqueDistanceDirective] // 要复用的话记得导出 }) export class YourFeatureModule { }
方案二:组件内直接验证(快速实现,仅当前组件可用)
如果这个验证逻辑只在当前组件用,不想写指令,可以直接在组件类里写验证方法:
1. 组件类添加验证方法
import { Component } from '@angular/core'; @Component({ selector: 'app-your-component', templateUrl: './your-component.component.html', styleUrls: ['./your-component.component.css'] }) export class YourComponent { distanceArray: { distance: number }[] = [/* 初始化你的数组数据 */]; // 检查当前索引的距离值是否重复 isDistanceDuplicate(index: number): boolean { const currentValue = this.distanceArray[index].distance; if (!currentValue) return false; return this.distanceArray.some((item, i) => i !== index && item.distance === currentValue); } }
2. 模板中调用验证方法
修改模板里的mat-error部分:
<div *ngFor="let distanceVal of distanceArray;let i=index" layout-gt-xs="row"> <div flex="30" flex-offset="15"> <mat-form-field> <input matInput placeholder="Distance" type="number" [(ngModel)]="distanceVal.distance" name="distance{{i}}" #distanceInput="ngModel" > <mat-error *ngIf="distanceInput.dirty && isDistanceDuplicate(i)"> 该距离值已存在,请输入不同的数值 </mat-error> </mat-form-field> </div> </div>
额外注意事项
- 当数组添加/删除项时,两种方案都会自动重新验证,因为数据绑定会触发更新。
- 空值的处理逻辑可以根据你的需求调整,比如如果要求必须输入值,可以结合
required验证一起使用。
内容的提问来源于stack exchange,提问作者Harish
相关产品推荐
相关产品推荐

