dfm*_*tro 15 typescript angular angular-reactive-forms angular5
我正在使用带有Reactive表单的Angular 5,并且需要使用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
});
}
Run Code Online (Sandbox Code Playgroud)
但是,当我运行它时,我得到一个浏览器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)
Run Code Online (Sandbox Code Playgroud)
"记录这个!" 被重复记录,就像它被递归调用一样,这就是为什么它们是一个堆栈错误
如果我删除valueChanges.subscribe代码工作除了有条件地删除验证.
为什么递归调用valueChanges.subscribe?
Kar*_*ner 16
实际上,真正的答案是,如果你想订阅任何表单更改并且仍然在其中运行patchValue,那么你应该只将{emitEvent:false}选项添加到patchValue,因此修补不会触发另一个更改检测
码:
this.formGroup
.valueChanges
.subscribe( _ => {
this.formGroup.get( 'controlName' ).patchValue( _val, {emitEvent: false} );
} );
Run Code Online (Sandbox Code Playgroud)
PS.这也比逐个订阅每个表单控件以避免触发更改超出最大调用堆栈更为繁琐.特别是如果你有表格有100个控件订阅.
现在进一步详细说明,如果你仍然需要在订阅中更新VALalAndValidity,那么我建议你使用distinctUntilChanged rxjs运算符,只在某些值发生变化时运行订阅.
现在我们还必须使它成为一个自定义验证函数,因为默认情况下,distinctUntilChanged通过指针验证对象,并且每次更改时指针都是新的.
this.formGroup
.valueChanges
.distinctUntilChanged((a, b) => JSON.stringify(a) === JSON.stringify(b))
.subscribe( _ => {
this.formGroup.get( 'controlName' ).patchValue( _val, {emitEvent: false} );
this.formGroup.get( 'controlName' ).updateValueAndValidity();
} );
Run Code Online (Sandbox Code Playgroud)
瞧,我们正在修补和更新,而不会遇到最大的调用堆栈!
mpr*_*pro 15
我的回答是只发展这一块.
通过distinctUntilChanged()在管道中添加之前subscribe()避免"超出最大调用堆栈大小",因为
distinctUntilChanged方法仅在当前值与最后一个值不同时才会发出.
用法:
this.userForm.get('password')
.valueChanges.pipe(distinctUntilChanged())
.subscribe(val => {})
Run Code Online (Sandbox Code Playgroud)
Con*_*Fan 11
问题是您修改了valueChanges同一字段的事件处理程序内部字段的值,导致事件再次被触发:
this.userForm.get('loginTypeId').valueChanges.subscribe(
(loginTypeId: string) => {
...
this.userForm.get('loginTypeId').updateValueAndValidity(); <-- Triggers valueChanges!
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
16582 次 |
| 最近记录: |