Angular14中基于Angular Material实现带验证的自定义输入组件
实现Angular Material自定义输入组件并绑定表单验证
完全可以实现你要的效果,只需要让自定义组件对接Angular的表单体系,核心是实现ControlValueAccessor接口,并通过NgControl关联父组件的FormControl,这样父组件设置的验证规则会自动作用到自定义组件,错误提示也能按需展示。
步骤1:自定义组件实现ControlValueAccessor
在自定义输入组件中,注入NgControl来获取父组件的FormControl实例,同时实现ControlValueAccessor的四个方法,让组件能和Angular表单双向绑定:
import { Component, Input } from '@angular/core'; import { ControlValueAccessor, NgControl } from '@angular/forms'; import { MatFormFieldAppearance } from '@angular/material/form-field'; @Component({ selector: 'app-custom-input', templateUrl: './custom-input.component.html', styleUrls: ['./custom-input.component.scss'], }) export class CustomInputComponent implements ControlValueAccessor { @Input() label!: string; @Input() appearance: MatFormFieldAppearance = 'fill'; onChange: (value: string) => void = () => {}; onTouched: () => void = () => {}; disabled = false; constructor(public ngControl: NgControl) { // 将当前组件设为NgControl的valueAccessor ngControl.valueAccessor = this; } // 从父表单写入值到组件 writeValue(value: string): void {} // 注册值变化回调(通知父表单值更新) registerOnChange(fn: (value: string) => void): void { this.onChange = fn; } // 注册触摸回调(通知父表单组件已被触摸) registerOnTouched(fn: () => void): void { this.onTouched = fn; } // 设置组件禁用状态 setDisabledState(isDisabled: boolean): void { this.disabled = isDisabled; } // 判断是否需要显示错误 get hasError(): boolean { const control = this.ngControl.control; return !!(control && control.invalid && (control.touched || control.dirty)); } // 根据错误类型返回对应提示文本 get errorMessage(): string { const control = this.ngControl.control; if (!control) return ''; if (control.hasError('required')) { return `${this.label} 不能为空`; } if (control.hasError('minlength')) { const requiredLen = control.getError('minlength').requiredLength; return `${this.label} 长度至少为 ${requiredLen} 个字符`; } // 可扩展更多错误类型,比如email、maxlength等 return ''; } }
步骤2:自定义组件模板(关联Angular Material Input)
在模板中使用mat-form-field和mat-input,绑定值变化和触摸事件,并通过mat-error显示错误:
<mat-form-field [appearance]="appearance"> <mat-label>{{ label }}</mat-label> <input matInput [value]="ngControl.control?.value" (input)="onChange($event.target.value)" (blur)="onTouched()" [disabled]="disabled" /> <mat-error *ngIf="hasError">{{ errorMessage }}</mat-error> </mat-form-field>
步骤3:父组件中使用自定义组件并设置验证规则
在父组件的FormGroup中定义FormControl和验证规则,直接通过formControlName绑定到自定义组件:
父组件TS代码
import { Component } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], }) export class AppComponent { form: FormGroup; constructor(private fb: FormBuilder) { this.form = this.fb.group({ username: ['', [Validators.required, Validators.minLength(3)]], }); } onSubmit(): void { if (this.form.invalid) { // 标记所有控件为已触摸,触发错误提示 this.form.markAllAsTouched(); return; } // 处理表单提交逻辑 console.log(this.form.value); } }
父组件HTML代码
<form [formGroup]="form" (ngSubmit)="onSubmit()"> <app-custom-input formControlName="username" label="Username" ></app-custom-input> <button mat-raised-button color="primary" type="submit">提交</button> </form>
关键说明
- 通过
NgControl,自定义组件能直接访问父组件设置的FormControl,包括验证规则和错误状态 ControlValueAccessor接口是Angular表单与自定义组件通信的标准方式,确保组件支持formControlName/formControl绑定mat-error的显示时机由hasError控制,只有当控件无效且已触摸/修改时才会显示错误提示
内容的提问来源于stack exchange,提问作者Gradin98
相关产品推荐
相关产品推荐

