You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.10 12:18:00