我正在使用Angular 5和React式表单,需要使用valueChanges来动态禁用所需的验证
组件类:
export class UserEditor implements OnInit {
public userForm: FormGroup;
userName: FormControl;
firstName: FormControl;
lastName: FormControl;
email: FormControl;
loginTypeId: FormControl;
password: FormControl;
confirmPassword: FormControl;
...
ngOnInit() {
this.createFormControls();
this.createForm();
this.userForm.get('loginTypeId').valueChanges.subscribe(
(loginTypeId: string) => {
console.log("log this!");
if (loginTypeId === "1") {
console.log("disable validators");
Validators.pattern('^[0-9]{5}(?:-[0-9]{4})?$')]);
this.userForm.get('password').setValidators([]);
this.userForm.get('confirmPassword').setValidators([]);
} else if (loginTypeId === '2') {
console.log("enable validators");
this.userForm.get('password').setValidators([Validators.required, Validators.minLength(8)]);
this.userForm.get('confirmPassword').setValidators([Validators.required, Validators.minLength(8)]);
}
this.userForm.get('loginTypeId').updateValueAndValidity();
}
)
}
createFormControls() {
this.userName = new FormControl('', [
Validators.required,
Validators.minLength(4)
]);
this.firstName = new FormControl('', Validators.required);
this.lastName = new FormControl('', Validators.required);
this.email = new FormControl('', [
Validators.required,
Validators.pattern("[^ @]*@[^ @]*")
]);
this.password = new FormControl('', [
Validators.required,
Validators.minLength(8)
]);
this.confirmPassword = new FormControl('', [
Validators.required,
Validators.minLength(8)
]);
}
createForm() {
this.userForm = new FormGroup({
userName: this.userName,
name: new FormGroup({
firstName: this.firstName,
lastName: this.lastName,
}),
email: this.email,
loginTypeId: this.loginTypeId,
password: this.password,
confirmPassword: this.confirmPassword
});
}
然而,当我运行它时,我得到了一个浏览器javascript错误
UserEditor.html:82 ERROR RangeError: Maximum call stack size exceeded
at SafeSubscriber.tryCatcher (tryCatch.js:9)
at SafeSubscriber.webpackJsonp.../../../../rxjs/_esm5/Subscription.js.Subscription.unsubscribe (Subscription.js:68)
at SafeSubscriber.webpackJsonp.../../../../rxjs/_esm5/Subscriber.js.Subscriber.unsubscribe (Subscriber.js:124)
at SafeSubscriber.webpackJsonp.../../../../rxjs/_esm5/Subscriber.js.SafeSubscriber.__tryOrUnsub (Subscriber.js:242)
at SafeSubscriber.webpackJsonp.../../../../rxjs/_esm5/Subscriber.js.SafeSubscriber.next (Subscriber.js:186)
at Subscriber.webpackJsonp.../../../../rxjs/_esm5/Subscriber.js.Subscriber._next (Subscriber.js:127)
at Subscriber.webpackJsonp.../../../../rxjs/_esm5/Subscriber.js.Subscriber.next (Subscriber.js:91)
at EventEmitter.webpackJsonp.../../../../rxjs/_esm5/Subject.js.Subject.next (Subject.js:56)
at EventEmitter.webpackJsonp.../../../core/esm5/core.js.EventEmitter.emit (core.js:4319)
at FormControl.webpackJsonp.../../../forms/esm5/forms.js.AbstractControl.updateValueAndValidity (forms.js:3377)
“log this!”被重复记录和调用,就像递归调用一样,这就是为什么它们是堆栈错误的原因
如果我移除valueChanges.subscribe,则代码除了有条件地移除验证之外还可以工作。
为什么要递归调用valueChanges.subscribe?
8条答案
按热度按时间klsxnrf11#
尝试将
distinctUntilChanged()
添加到管道中subscribe()
之前。它应该过滤掉那些值实际上没有更改的“更改”事件。2jcobegt2#
我在执行验证时遇到了类似的错误。调用updateValueAndValidity()时出现错误。在我的示例中,我使用了此重载updateValueAndValidity({emitEvent:错误})
试试这个
这个.userForm.get('登录类型Id').更新值和有效性({emitEvent:false});
ef1yzkbh3#
如果您需要启用全选,请选择您的表单
f1tvaqid4#
也许这个链接会解决这个和其他案件
https://github.com/angular/angular/issues/11205
2uluyalo5#
在我的例子中,当我试图更新表单控件的值和有效性时,它确实被
{ emitEvent: false }
附加项修复了:ppcbkaq56#
如果您希望订阅任何表单更改并仍在其中运行patchValue,则可以将
{emitEvent: false}
选项添加到patchValue,这样打补丁就不会触发另一个更改检测密码:
这也比一个接一个地订阅每个表单控件来避免触发超过最大调用栈的更改要少得多。特别是当您的表单有100个控件要订阅时。
现在进一步详细说明,如果您仍然需要在订阅中使用updateValueAndValidity,那么我建议您使用
distinctUntilChanged
rxjs操作符,以便仅在某些值发生更改时运行订阅。distinctUntilChanged文档可在此处找到
https://www.learnrxjs.io/operators/filtering/distinctuntilchanged.html
distinctUntilChanged-仅在当前值与上一个值不同时发出。
现在,我们还必须使它成为一个自定义的验证函数,因为在默认情况下,distinctUntilChanged通过指针验证对象,并且每次更改时指针都是新的。
瞧,我们正在修补和更新,而不会运行到最大调用堆栈!
sf6xfgos7#
我的答案是开发this one。
通过在管道中
subscribe()
之前添加distinctUntilChanged()
,可以避免“超出最大调用堆栈大小”,因为distinctUntilChanged方法仅在当前值与上一个值不同时发出。
用法:
Documentation
ghhkc1vu8#
问题在于,您在
valueChanges
事件行程常式中修改相同字段的字段值,导致事件再次触发: