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

Angular 10 Reactive Form按条件隐藏输入项后表单无法提交问题

问题根因

Angular响应式表单的校验逻辑和控件是否在DOM中渲染无关,你初始化表单时同时给firstName和lastName都加了Validators.required必填校验,就算用*ngIf隐藏了其中一个输入框,对应的表单控件依然存在且处于必填校验生效的状态,隐藏的控件值为空就会导致整个表单校验不通过,无法提交。

解决步骤

1. 修改app.component.ts逻辑

需要在切换单选框的时候,动态给对应控件增加/移除必填校验,同时更新控件的校验状态:

import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ReCaptchaV3Service } from 'ngx-captcha';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'testproject';
  registerForm: FormGroup;
  siteKey: any;
  submitted = false;
  firstNames = true;

  constructor(private formBuilder: FormBuilder, private reCaptchaV3Service: ReCaptchaV3Service) { }

  ngOnInit() {
    this.registerForm = this.formBuilder.group({
      title: ['', Validators.required],
      firstName: ['', Validators.required],
      // 初始隐藏lastName,所以初始不加必填校验
      lastName: ['']
    });
  }

  showFirstName(){
    this.firstNames = true;
    // 给firstName加必填,移除lastName的必填
    this.registerForm.get('firstName').addValidators(Validators.required);
    this.registerForm.get('lastName').removeValidators(Validators.required);
    // 更新两个控件的校验状态
    this.registerForm.get('firstName').updateValueAndValidity();
    this.registerForm.get('lastName').updateValueAndValidity();
  }

  showLastName(){
    this.firstNames = false;
    // 给lastName加必填,移除firstName的必填
    this.registerForm.get('lastName').addValidators(Validators.required);
    this.registerForm.get('firstName').removeValidators(Validators.required);
    // 更新两个控件的校验状态
    this.registerForm.get('lastName').updateValueAndValidity();
    this.registerForm.get('firstName').updateValueAndValidity();
  }

  get f() { return this.registerForm.controls; }

  onSubmit() {
    this.submitted = true;
    if (this.registerForm.invalid) {
      return;
    }
    // 提交的时候过滤掉未选中的字段
    const submitValue = {...this.registerForm.value};
    if (this.firstNames) {
      delete submitValue.lastName;
    } else {
      delete submitValue.firstName;
    }
    alert('提交成功! :-)\n' + JSON.stringify(submitValue, null, 4));
  }

  onReset() {
    this.submitted = false;
    this.firstNames = true;
    // 重置的时候恢复初始校验状态
    this.registerForm.get('firstName').addValidators(Validators.required);
    this.registerForm.get('lastName').removeValidators(Validators.required);
    this.registerForm.reset();
  }
}

2. 修改app.component.html的对应问题

修正单选框的点击事件绑定、文字错误以及选中状态默认值:

<div class="card m-3">
    <h5 class="card-header">Angular 10 响应式表单校验</h5>
    <div class="card-body">
        <form [formGroup]="registerForm" (ngSubmit)="onSubmit()">
            <div class="form-row">
                <div class="form-group col">
                    <label>称谓</label>
                    <select formControlName="title" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.title.errors }">
                        <option value=""></option>
                        <option value="Mr">先生</option>
                        <option value="Mrs">夫人</option>
                        <option value="Miss">小姐</option>
                        <option value="Ms">女士</option>
                    </select>
                    <div *ngIf="submitted && f.title.errors" class="invalid-feedback">
                        <div *ngIf="f.title.errors.required">称谓为必填项</div>
                    </div>
                </div>
                <div ><input (click)="showFirstName()" name="fname" type="radio" [checked]="firstNames"> 显示名字</div>
                <div ><input (click)="showLastName()" name="fname" type="radio" [checked]="!firstNames"> 显示姓氏</div>
                               
                <div class="form-group col-5" *ngIf="firstNames">
                    <label>名字</label>
                    <input type="text" formControlName="firstName" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.firstName.errors }" />
                    <div *ngIf="submitted && f.firstName.errors" class="invalid-feedback">
                        <div *ngIf="f.firstName.errors.required">名字为必填项</div>
                    </div>
                </div>
                <div class="form-group col-5" *ngIf="!firstNames">
                    <label>姓氏</label>
                    <input type="text" formControlName="lastName" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.lastName.errors }" />
                    <div *ngIf="submitted && f.lastName.errors" class="invalid-feedback">
                        <div *ngIf="f.lastName.errors.required">姓氏为必填项</div>
                    </div>
                </div>
                             
            </div>
            <div class="text-center">
                <button class="btn btn-primary mr-1">注册</button>
                <button class="btn btn-secondary" type="reset" (click)="onReset()">取消</button>
            </div>
        </form>
    </div>
</div>

可选优化方案

也可以选择动态增删表单控件的方式实现,切换单选框的时候用addControl和removeControl方法增减对应控件,不需要手动处理校验状态,逻辑更简洁。

内容的提问来源于stack exchange,提问作者uiankosh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 11:54:03