@IT·互联网

angular 两表单控件值双向关联

2021-04-20  本文已影响0人  云上笔记

业务场景:

改变 model A,model B 的值改变;
改变 model B,model A 的值也改变。

例如:buy/selllong/short字段分别有两个下拉选项, buy/sell 值为buy 时,long/short 值自动改为 long, 反之亦然

ngModel联动.gif
看到这个效果,首先想到的是不是用两个ngModelChange事件直接改变另一项的值
// html
<lable>buy/sell</label>
<nz-select formControlName="buy_sell" (ngModelChange)="chooseBuySell($event)">
    <nz-option nzLabel="BUY" nzValue="BUY"></nz-option>
    <nz-option nzLabel="SELL" nzValue="SELL"></nz-option>
</nz-select>

<lable>long/short</label>
<nz-select formControlName="long_short" (ngModelChange)="chooseLongShort($event)">
    <nz-option nzLabel="LONG" nzValue="LONG"></nz-option>
    <nz-option nzLabel="SHORT" nzValue="SHORT"></nz-option>
</nz-select>
  /**
   * components
   * buy/sell 选择 buy 时,long/short 自动选择long,反之亦然
   */
  public chooseBuySell(val) {
    const res = val.toLowerCase();
    if (res === 'buy') {
      this.detailForm.get('long_short').patchValue('LONG');
    } else {
      this.detailForm.get('long_short').patchValue('SHORT');
    }
  }

  public chooseLongShort(val) {
    const res = val.toLowerCase();
    if (res === 'long') {
      this.detailForm.get('buy_sell').patchValue('BUY');
    } else {
      this.detailForm.get('buy_sell').patchValue('SELL');
    }
  }

运行代码,发现报错

error.png
这是因为,当你改变其中一项时,触发了当前项的ngModelChange事件,而该事件中的patchValue给另一个表单项赋值的时候,另一项ngModel的值已经改变,从而触发了另一项的ngModelChange事件,如此就会导致两个ngModelChange事件不断被触发,从而爆栈 图片.png

那么,有什么办法可以解决这个问题呢?
通过查看 FormControl patchValue()函数的源码,可以发现该函数提供了一个emitEvent参数,如果设为 true或未提供(默认),则当控件值变化时, statusChangesvalueChanges这两个 Observable 都会以最近的状态和值发出事件。 如果为 false,则不会发出事件。
因此我们通过设置emitEvent: false 来延迟更新控件的值

图片.png

如下更改代码后,可以实现该效果

// html
<lable>buy/sell</label>
<nz-select formControlName="buy_sell" (ngModelChange)="chooseBuySell($event)">
    <nz-option nzLabel="BUY" nzValue="BUY"></nz-option>
    <nz-option nzLabel="SELL" nzValue="SELL"></nz-option>
</nz-select>

<lable>long/short</label>
<nz-select [ngModel]="detailForm.value.long_short" 
           [ngModelOptions]="{standalone: true}" 
           (ngModelChange)="chooseLongShort($event)">
      <nz-option nzLabel="LONG" nzValue="LONG"></nz-option>
      <nz-option nzLabel="SHORT" nzValue="SHORT"></nz-option>
</nz-select>
  /**
   * components
   * buy/sell 选择 buy 时,long/short 自动选择long,反之亦然
   */
  public chooseBuySell(val) {
    const res = val.toLowerCase();
    if (res === 'buy') {
      this.detailForm.get('long_short').patchValue('LONG', { emitEvent: false });
    } else {
      this.detailForm.get('long_short').patchValue('SHORT', { emitEvent: false });
    }
  }

  public chooseLongShort(val) {
    const res = val.toLowerCase();
    this.detailForm.get('long_short').patchValue(val, { emitEvent: false });
    if (res === 'long') {
      this.detailForm.get('buy_sell').patchValue('BUY');
    } else {
      this.detailForm.get('buy_sell').patchValue('SELL');
    }
  }
上一篇 下一篇

猜你喜欢

热点阅读