脚本:
最初,我有一个文本框(Name1
)、一个日期选择器(DOB1
)和一个复选框(Compare
)。Name1
和DOB1
都是必需的。单击复选框时,将动态添加两个名为Name2
和DOB2
的表单控件,并且需要Name1
或DOB2
中的任何一个控件。
所以有效的表格上有Name1
DOB1
Name2
或//Name2
DOB2
Name1
或//DOB1
DOB2
DOB2
Name2
Name1
在上述所有情况下,表单都是有效的“显示启用提交”按钮。
问题:
我试过使用setvalidators,但仍然不知道我缺少什么。当我单击复选框时,只有当所有四个控件都有效时,表单才有效。我只需要三个有效的。
代码:
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
<ion-card class="person1">
<ion-card-content>
<ion-list lines="full" class="ion-no-margin ion-no-padding">
<ion-item>
<ion-label position="stacked">Name / Number <ion-text color="danger">*</ion-text>
</ion-label>
<ion-input type="text" formControlName="NameNumber"></ion-input>
</ion-item>
<ion-item>
<ion-label position="stacked">Date of birth<ion-text color="danger">*</ion-text>
</ion-label>
<ion-datetime required placeholder="Select Date" formControlName="DateOfBirth"></ion-datetime>
</ion-item>
</ion-list>
</ion-card-content>
</ion-card>
<ion-card class="person2" *ngIf="isComparisonChecked">
<ion-card-content>
<ion-list lines="full" class="ion-no-margin ion-no-padding">
<ion-item>
<ion-label position="stacked">Name / Number <ion-text color="danger">*</ion-text>
</ion-label>
<ion-input type="text" formControlName="NameNumber2"></ion-input>
</ion-item>
<ion-item>
<ion-label position="stacked">Date of birth<ion-text color="danger">*</ion-text>
</ion-label>
<ion-datetime required placeholder="Select Date" formControlName="DateOfBirth2"></ion-datetime>
</ion-item>
</ion-list>
</ion-card-content>
</ion-card>
<ion-item class="compare-section" lines="none">
<ion-label>Compare</ion-label>
<ion-checkbox color="danger" formControlName="IsCompare"></ion-checkbox>
</ion-item>
<div class="ion-padding">
<ion-button color="danger" *ngIf="LicensedStatus" [disabled]="!this.profileForm.valid" expand="block"
type="submit" class="ion-no-margin">Submit</ion-button>
</div>
</form>
Ts:
profileForm = new FormGroup({
NameNumber: new FormControl('', [Validators.required, Validators.pattern('^[A-Za-z0-9 _]*[A-Za-z0-9][A-Za-z0-9 _]*$')]),
DateOfBirth: new FormControl('', Validators.required),
IsCompare: new FormControl(false)
});
...
this.profileForm.get('IsCompare').valueChanges.subscribe(checked => {
if (checked) {
this.profileForm.addControl('NameNumber2', new FormControl('', [Validators.required, Validators.pattern('^[A-Za-z0-9 _]*[A-Za-z0-9][A-Za-z0-9 _]*$')]));
this.profileForm.addControl('DateOfBirth2', new FormControl('', Validators.required));
this.profileForm.get('NameNumber2').valueChanges.subscribe(() => {
if (this.profileForm.get('NameNumber2').valid) {
this.profileForm.get('DateOfBirth2').clearValidators();
}
else {
this.profileForm.get('DateOfBirth2').setValidators([Validators.required]);
}
this.profileForm.get('DateOfBirth2').updateValueAndValidity();
});
this.profileForm.get('DateOfBirth2').valueChanges.subscribe(() => {
if (this.profileForm.get('DateOfBirth2').valid) {
this.profileForm.get('NameNumber2').clearValidators();
}
else {
this.profileForm.get('NameNumber2').setValidators([Validators.required, Validators.pattern('^[A-Za-z0-9 _]*[A-Za-z0-9][A-Za-z0-9 _]*$')]);
}
this.profileForm.get('NameNumber2').updateValueAndValidity();
});
}
else {
this.profileForm.removeControl('NameNumber2');
this.profileForm.removeControl('DateOfBirth2');
}
});
我错过了什么?
更新第1号:
我已经更新了上面的代码。如果我使用
DOB1
控制台中会出现此错误最佳答案
这是因为updateValueAndValidity()
发出另一个valueChanges
事件。所以你们的订阅会无限地相互触发。
this.profileForm.get('NameNumber2').valueChanges.subscribe(() => {
// omitted
this.profileForm.get('DateOfBirth2').updateValueAndValidity(); // Triggers valueChanges for 'DateOfBirth2'
});
this.profileForm.get('DateOfBirth2').valueChanges.subscribe(() => {
// omitted
this.profileForm.get('NameNumber2').updateValueAndValidity(); // Triggers valueChanges for 'NameNumber2'
});
避免这种情况的一种方法已经在前面的文章中描述过:使用
distinctUntilChanged
。方法本身内置了一个更干净的方法:
updateValueAndValidity()
接受一个对象来配置其行为。updateValueAndValidity({emitEvent: false})
将阻止发出valueChanges
事件,从而停止事件循环。this.profileForm.get('NameNumber2').valueChanges.subscribe(() => {
// omitted
this.profileForm.get('DateOfBirth2').updateValueAndValidity({emitEvent:false}); // Does NOT trigger valueChanges
});
this.profileForm.get('DateOfBirth2').valueChanges.subscribe(() => {
// omitted
this.profileForm.get('NameNumber2').updateValueAndValidity({emitEvent:false}); // Does NOT trigger valueChanges
});
关于angular - 根据条件动态添加/删除验证器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57038703/