角度:超过多个值的最大调用堆栈大小

时间:2019-11-12 17:20:16

标签: angular angular-reactive-forms

注意-我在结尾处加入了stackblitz链接。

我的代码有问题,如果当前正在填充另一个formcontrol,则我希望实质上禁用formcontrol。例如,如果填充了字段A,则将禁用输入字段B和C。如果清除了字段A,则字段B和C将重新启用。这会在三个字段中按其各自的顺序发生,这意味着如果您填充B,则A和C将被禁用,等等。

this.SearchForm.get('a').valueChanges
    .subscribe( ( value ) => {
      if ( value ) {
        this.SearchForm.get('b').disable();
        this.SearchForm.get('c').disable();
      } else {
        this.SearchForm.get('b').enable();
        this.SearchForm.get('c').enable();
      }
    });

如果我仅在一个字段上进行设置,则效果很好。但是,如果我将其更改为包括如下所述设置其他字段:

this.SearchForm.get('a').valueChanges
    .subscribe( ( value ) => {
      if ( value ) {
        this.SearchForm.get('b').disable();
        this.SearchForm.get('c').disable();
      } else {
        this.SearchForm.get('b').enable();
        this.SearchForm.get('c').enable();
      }
    });

    this.SearchForm.get('b').valueChanges
    .subscribe( ( value ) => {
      if ( value ) {
        this.SearchForm.get('a').disable();
        this.SearchForm.get('c').disable();
      } else {
        this.SearchForm.get('a').enable();
        this.SearchForm.get('c').enable();
      }
    });

    this.SearchForm.get('c').valueChanges
    .subscribe( ( value ) => {
      if ( value ) {
        this.SearchForm.get('a').disable();
        this.SearchForm.get('b').disable();
      } else {
        this.SearchForm.get('a').enable();
        this.SearchForm.get('b').enable();
      }
    });

我收到“超出最大调用堆栈大小”错误。也许有一种更好的方法可以通过反应形式来做到这一点,但是我还没有遇到任何东西。之所以采用这种方法,部分原因是因为一旦该字段为空,它将以更少的代码轻松地重新启用其他字段。

Link of Stackblitz 如果将b和c的valueChanges注释掉并且只有一个,则可以看到我正在寻找的行为,但是,如果再添​​加一个额外的valuechanges,则会出现错误。

2 个答案:

答案 0 :(得分:1)

disable()/ enable()方法有一个emitEvent选项:

disable(opts: { onlySelf?: boolean; emitEvent?: boolean; } = {}): void
enable(opts: { onlySelf?: boolean; emitEvent?: boolean; } = {}): void

https://angular.io/api/forms/AbstractControl

尝试传递{ emitEvent: false }

const disableEnableOptions = {emitEvent: false };
this.SearchForm.get('a').valueChanges
    .subscribe( ( value ) => {
      if ( value ) {
        this.SearchForm.get('b').disable(disableEnableOptions);
        this.SearchForm.get('c').disable(disableEnableOptions);
      } else {
        this.SearchForm.get('b').enable(disableEnableOptions);
        this.SearchForm.get('c').enable(disableEnableOptions);
      }
    });

这应该阻止您的更改触发其他订阅者。您应该能够在其余的代码中实现这一点。

这是我为您带来的闪电战的分支:https://stackblitz.com/edit/angular-w5r29c

答案 1 :(得分:0)

将值更改称为“ a”时,将调用另一个值更改,依此类推,直到达到调用堆栈限制。

基本上完整的表单映射在模型上,因此,每当启用/禁用任何控件时,表单模型的属性都会更改。而且由于模型正在更改,因此将触发valueChanges事件。

如果您使用的是新版本的angular,则可以使用

this.form.get('b')。setValue(newValue,{onlySelf:true,发射事件:false});