我的申请中有一份复杂的表格。其中一部分要求提供地址,他们必须输入实际地址。有一个复选框用于标记邮寄地址是否相同。如果是,则不需要邮寄地址字段(这是默认值)。如果取消选中该复选框,则需要输入邮寄地址。这种方法是有效的,因为最初不需要邮寄地址,但在取消选中该框后,邮寄地址变成必需的。但如果他们再次检查,仍然需要输入邮寄地址。这是相关的代码片段:
// form declaration
const personalInfoForm = this._fb.group(
{
sameAddress: [true],
physicalAddress: this._fb.group({
line1: [
"",
[Validators.required, MhaValidators.validPhysicalStreetAddress],
],
city: ["", [Validators.required]],
state: ["", [Validators.required]],
zip: ["", [Validators.required, MhaValidators.validZipCode]],
}),
mailingAddress: this._fb.group({
line1: [""],
city: [""],
state: [""],
zip: [""],
}),
}
);
// valueChanges for same address
this.personalInfoForm
.get("sameAddress")
.valueChanges.pipe(
startWith(this.personalInfoForm.get("sameAddress").value),
tap((sameAddress: boolean) => {
if (sameAddress) {
this.personalInfoForm.controls.mailingAddress = this._fb.group({
line1: [""],
city: [""],
state: [""],
zip: [""],
});
} else {
this.personalInfoForm.controls.mailingAddress = this._fb.group({
line1: ["", [Validators.required]],
city: ["", [Validators.required]],
state: ["", [Validators.required]],
zip: ["", [Validators.required, MhaValidators.validZipCode]],
});
}
this.personalInfoForm.controls.mailingAddress.updateValueAndValidity();
this.personalInfoForm.updateValueAndValidity();
}),
untilDestroyed(this)
)
.subscribe();
// I also tried this for updating the validators:
this.personalInfoForm
.get("sameAddress")
.valueChanges.pipe(
startWith(this.personalInfoForm.get("sameAddress").value),
tap((sameAddress: boolean) => {
const mailingAddress: FormGroup = this.personalInfoForm.get(
"mailingAddress"
) as FormGroup;
if (sameAddress) {
// remove validators from mailing address
mailingAddress.get("line1").clearValidators();
mailingAddress.get("city").clearValidators();
mailingAddress.get("state").clearValidators();
mailingAddress.get("zip").clearValidators();
} else {
// add validators to mailing address
mailingAddress.get("line1").addValidators([Validators.required]);
mailingAddress.get("city").addValidators([Validators.required]);
mailingAddress.get("state").addValidators([Validators.required]);
mailingAddress
.get("zip")
.addValidators([Validators.required, MhaValidators.validZipCode]);
}
this.personalInfoForm.updateValueAndValidity();
}),
untilDestroyed(this)
)
.subscribe();
本质上,我想在
sameAddress
控件在 true 和 false 之间来回切换时添加或删除字段的验证器。
现在,如果他们不更改相同的地址控件,该表单在技术上就可以工作。如果他们取消选择它,即使他们重新选择该复选框,他们也需要填写邮寄地址。
我不确定为什么有效性没有正确更新。有什么想法吗?
下面是一个基本的工作示例,我认为一旦设置了验证器,您需要运行该特定表单控件的
updateValueAndValidity
,之后代码运行正常!
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import {
FormBuilder,
FormGroup,
ReactiveFormsModule,
Validators,
} from '@angular/forms';
import { bootstrapApplication } from '@angular/platform-browser';
import { tap } from 'rxjs';
import { startWith } from 'rxjs/operators';
import 'zone.js';
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule, ReactiveFormsModule],
template: `
<form [formGroup]="personalInfoForm" (ngSubmit)="onSubmit()">
<input formControlName="sameAddress" type="checkbox"/>
<fieldset formGroupName="physicalAddress">
physicalAddress | line1 :
<input formControlName="line1" type="text"/>
</fieldset>
<fieldset formGroupName="mailingAddress">
mailingAddress | line1 :
<input formControlName="line1" type="text"/>
</fieldset>
<button type="submit">submit</button>
</form>
`,
})
export class App {
name = 'Angular';
personalInfoForm: FormGroup = new FormGroup({});
constructor(private _fb: FormBuilder) {}
onSubmit() {
if (this.personalInfoForm.invalid) {
alert('invalid');
}
console.log('submit');
}
ngOnInit(): void {
const personalInfoForm = this._fb.group({
sameAddress: [true],
physicalAddress: this._fb.group({
line1: ['', [Validators.required]],
}),
mailingAddress: this._fb.group({
line1: [''],
}),
});
this.personalInfoForm = personalInfoForm;
// I also tried this for updating the validators:
this.personalInfoForm!.get('sameAddress')!
.valueChanges.pipe(
startWith(this.personalInfoForm.get('sameAddress')!.value),
tap((sameAddress: boolean) => {
console.log(sameAddress);
const mailingAddress: FormGroup = this.personalInfoForm.get(
'mailingAddress'
) as FormGroup;
const mailAddressLine1Ctrl = mailingAddress.get('line1');
if (sameAddress) {
// remove validators from mailing address
mailAddressLine1Ctrl!.clearValidators();
} else {
// add validators to mailing address
mailAddressLine1Ctrl!.addValidators([Validators.required]);
}
mailAddressLine1Ctrl!.updateValueAndValidity(); // <-- fix here
})
)
.subscribe();
}
}
bootstrapApplication(App);