Angular中表单外提交按钮点击后如何聚焦首个无效输入框
实现方案
有两种常用实现方式,可根据项目复用需求选择:
方式1:自定义指令实现(复用性高,适合多表单场景)
你代码中form标签上已经标注了focusInvalidInput指令标识,我们可以直接实现该指令完成通用聚焦逻辑:
1. 编写自定义指令代码
import { Directive, ElementRef, Input } from '@angular/core'; import { FormGroupDirective } from '@angular/forms'; @Directive({ selector: '[focusInvalidInput]' }) export class FocusInvalidInputDirective { @Input() formGroupDirective!: FormGroupDirective; constructor(private el: ElementRef<HTMLFormElement>) {} // 对外暴露触发聚焦的方法 triggerFocusFirstInvalid(): void { // 找到表单内第一个带ng-invalid类的可输入元素 const invalidControl = this.el.nativeElement.querySelector<HTMLInputElement>( 'input.ng-invalid, select.ng-invalid, textarea.ng-invalid' ); invalidControl?.focus(); // 可选配置:需要滚动到对应位置可添加如下代码 // invalidControl?.scrollIntoView({ behavior: 'smooth', block: 'center' }) } }
2. 改造HTML绑定
<!-- 给指令绑定当前的表单Group实例 --> <form focusInvalidInput [formGroup]="form" #focusDir="focusInvalidInput"> <label for="first">First Name</label> <input formControlName="first" /> <label for="last">Last Name</label> <input formControlName="last" /> <br /> </form> <button (click)="submit(focusDir)">submit</button>
3. 改造组件submit逻辑
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { FocusInvalidInputDirective } from './focus-invalid-input.directive'; // ...组件内代码 form: FormGroup; constructor(private formBuilder: FormBuilder) { this.form = this.formBuilder.group({ first: ['', Validators.required], last: ['', Validators.required], }); } submit(focusDir: FocusInvalidInputDirective) { // 先标记所有控件为已触碰,触发校验样式更新 this.form.markAllAsTouched(); if (this.form.valid) { console.log(this.form); return; } // 校验失败触发首个无效控件聚焦 focusDir.triggerFocusFirstInvalid(); }
方式2:组件内直接实现(不需要额外指令,快速适配单个场景)
如果只有单个表单需要该逻辑,可以直接在组件内通过ViewChild获取表单DOM处理,不需要额外创建指令:
1. 改造HTML给表单加标识
<form [formGroup]="form" #myForm> <label for="first">First Name</label> <input formControlName="first" /> <label for="last">Last Name</label> <input formControlName="last" /> <br /> </form> <button (click)="submit()">submit</button>
2. 改造组件代码
import { Component, ElementRef, ViewChild } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; // ...组件内代码 form: FormGroup; @ViewChild('myForm') formEl!: ElementRef<HTMLFormElement>; constructor(private formBuilder: FormBuilder) { this.form = this.formBuilder.group({ first: ['', Validators.required], last: ['', Validators.required], }); } submit() { this.form.markAllAsTouched(); if (this.form.valid) { console.log(this.form); return; } // 直接查找第一个无效控件聚焦 const invalidControl = this.formEl.nativeElement.querySelector<HTMLInputElement>( 'input.ng-invalid, select.ng-invalid, textarea.ng-invalid' ); invalidControl?.focus(); }
内容的提问来源于stack exchange,提问作者Fash
相关产品推荐
相关产品推荐

