业务场景:
改变 model A,model B 的值改变;
改变 model B,model A 的值也改变。
例如:buy/sell
和long/short
字段分别有两个下拉选项, buy/sell 值为buy
时,long/short 值自动改为 long
, 反之亦然

看到这个效果,首先想到的是不是用两个
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');
}
}
运行代码,发现报错

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

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

如下更改代码后,可以实现该效果
// 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');
}
}
网友评论