Angular自定义名称重复校验求助:mat-error提示异常
Angular自定义重复名称校验问题修复
问题说明
在Angular中实现自定义校验:当输入的名称与TS文件中定义的学生对象数组内的名称重复时,mat-error显示“名称已存在”提示。当前校验逻辑存在问题,以下是修复方案。
原代码
app.html
<form [formGroup]="form"> <div> <mat-form-field> <input matInput type="text" [formControl]="name" required /> <mat-error *ngIf="name.hasError('required')"> 此项为必填项 </mat-error> <mat-error *ngIf="name.hasError('validateName')"> 名称已存在 </mat-error> </mat-form-field> </div> </form>
app.ts
import { Component, OnInit } from '@angular/core'; import { FormGroup, FormBuilder, Validators, AbstractControl, ValidationErrors } from '@angular/forms'; @Component({ selector: 'app-formulario', templateUrl: './component.html', styleUrls: ['./component.scss'], }) export class AdminMaintainerFormsDialogComponent implements OnInit{ public form: FormGroup; public name: AbstractControl; public totalStudents: any = [ { name: "Sandro", rol: "student" }, { name: "Paola", rol: "student" } ]; constructor( private fb: FormBuilder) { } ngOnInit() { this.start(); } start() { this.form = this.fb.group({ name: ['', Validators.compose([Validators.required, this.validateName ])] }); } private validateName(control: AbstractControl): ValidationErrors | null { const names = this.totalStudents; let compareName; names.map(value => { compareName = value.name; }) return compareName.test(control.value) ? null : { validateName: { valid: false } }; } }
问题分析
- 遍历逻辑错误:用
map遍历数组时,compareName最终只会被赋值为数组最后一个元素的名称,无法覆盖所有已存在的名称。 - 方法使用错误:
test()是正则表达式专属方法,但compareName是普通字符串,调用该方法会直接报错。 - 校验逻辑颠倒:当前逻辑是输入值匹配单个名称时返回校验通过,与“重复则报错”的需求完全相反。
- 控件未绑定:TS中的
name控件未从表单实例中获取引用,导致HTML中的[formControl]="name"无法正确关联。
修复后的代码
app.ts
import { Component, OnInit } from '@angular/core'; import { FormGroup, FormBuilder, Validators, AbstractControl, ValidationErrors } from '@angular/forms'; @Component({ selector: 'app-formulario', templateUrl: './component.html', styleUrls: ['./component.scss'], }) export class AdminMaintainerFormsDialogComponent implements OnInit{ public form: FormGroup; public name: AbstractControl; public totalStudents: any = [ { name: "Sandro", rol: "student" }, { name: "Paola", rol: "student" } ]; constructor( private fb: FormBuilder) { } ngOnInit() { this.start(); } start() { this.form = this.fb.group({ // 绑定this确保校验器能访问组件内的totalStudents name: ['', Validators.compose([Validators.required, this.validateName.bind(this) ])] }); // 关联表单控件实例 this.name = this.form.get('name'); } private validateName(control: AbstractControl): ValidationErrors | null { const inputName = control.value?.trim().toLowerCase(); // 空值直接返回,让必填校验生效 if (!inputName) return null; // 检查输入名称是否在学生数组中存在 const isDuplicate = this.totalStudents.some(student => student.name.toLowerCase() === inputName ); // 重复则返回错误标记,否则校验通过 return isDuplicate ? { validateName: true } : null; } }
补充说明
- 绑定
this:自定义校验器传入表单时必须用bind(this),否则无法访问组件内的totalStudents数组。 - 大小写处理:代码中加入了
toLowerCase()实现忽略大小写的校验,若需要严格区分大小写,可直接移除该方法。 - 空值过滤:输入为空时直接返回
null,避免干扰必填项的校验逻辑。
内容的提问来源于stack exchange,提问作者Emanuel
相关产品推荐
相关产品推荐

