【问题标题】:Is it possible to trigger statusChanges without triggering valueChanges on a reactive form control?是否可以在不触发反应表单控件上的 valueChanges 的情况下触发 statusChanges?
【发布时间】:2020-01-24 10:57:14
【问题描述】:

我有一个带有多个嵌套组和控件的FormGroup。其中大部分包含验证器,例如Validators.required。每当用户单击提交按钮时,我都会递归地遍历表单以确保每个验证器都被触发并且每个控件都有效。这是通过将每个控件标记为已触摸并调用 control.updateValueAndValidity() 来完成的。

但是,这会同时触发 valueChangedstatusChanged 事件。我已将订阅者添加到 statusChanged 事件,该事件应该处理任何错误,但我不希望触发 valueChanged,因为值没有改变。

是否可以在不触发valueChanged 的情况下手动触发statusChanged?将{ emitEvent: false } 传递给updateValueAndValidity 将阻止这两个事件被触发。

public ngOnInit(): void {
    const form = this.formBuilder.group({
        'name': ['', Validators.required],
        'address': this.formBuilder.group({
            'street': ['', Validators.required],
            'number': ['', Validators.required]
        })
    });

    form.valueChanges.subscribe(() => console.log('Should not fire'));
    form.statusChanges.subscribe(() => console.log('Should fire'));

    this.validateForm(form);

    console.log(form.valid);
}

private validateForm(control: AbstractControl): void {
    if (control instanceof FormControl) {
        control.markAsTouched();
        control.markAsDirty();
        control.updateValueAndValidity();
    } else if (control instanceof FormGroup) {
        Object.keys(control.controls).forEach(field => {
            this.validateForm(control.get(field));
        });
    }
}

// should print 'Should fire' and 'false' but not 'Should not fire'

【问题讨论】:

  • 为什么不使用Custom validators?使用验证器,您只需检查表单的全局验证。
  • @ThierryFalvo 你能给我一个例子来让我的代码示例工作吗?我不太明白使用自定义验证器如何解决问题。
  • 也许我没有清楚地了解您的需求。为什么 validateForm 的目标是? Angular 文档(提供链接)中提到的自定义验证器使您能够检查和验证每个表单控件,然后无需迭代每个字段以手动检查它们。
  • @ThierryFalvo 因为我订阅了statusChanges 以监听验证更改。每当它被触发时,我都会检查任何验证错误并将它们显示给用户。根据角度docs,这是“一个多播可观察对象,每次重新计算控件的验证状态时都会发出一个事件”,这似乎非常适合我使用它。如果我不调用 validateForm,valueChanges 将永远不会被触发并且不会显示任何验证消息。
  • 我的意思是使用自定义验证器可以避免这样做,错误可能会显示在模板 <div *ngIf="name.errors.forbiddenName">Name cannot be Bob.</div> 中。如果无效,您只需要阻止提交表单。

标签: angular angular-reactive-forms


【解决方案1】:

statusChanges 属性实际上是一个 EventEmitter,因此您可以将其转换为手动发出状态:

(<EventEmitter<any>> control.statusChanges).emit(control.status);

【讨论】:

  • 请考虑在您的答案中添加一些解释和细节。虽然它可能会回答问题,但仅添加一些代码并不能帮助 OP 或未来的社区成员理解问题或解决方案。
  • 注意,我已经为解决方案添加了更多细节。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-06
  • 2013-04-24
  • 2018-11-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多