You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 7中FormArray内Select控件值变更时动态显示对应Div

解决Angular 7响应式表单FormArray中Select控件的条件显示问题

嘿,我刚好碰到过类似的场景,给你几个靠谱的解决方案,完全贴合响应式表单的规范,不用再依赖已弃用的[(ngModel)]啦!

首先先纠正一个小细节:你模板里的select用了formControlName="sentCondition",但你的FormGroup里定义的控件名是condition,先把这个统一成condition,不然表单控件会找不到对应的FormControl哦。

方案一:模板中直接访问FormControl的值(最直接)

在FormArray的循环里,每个项都是一个FormGroup,我们可以直接通过这个FormGroup获取condition控件的当前值,用来做*ngIf的判断条件。

模板代码修改:

<!-- 外层包裹FormArray -->
<div formArrayName="listFieldArray">
  <!-- 循环每个FormArray项 -->
  <div *ngFor="let fieldGroup of listFieldArray.controls; let i = index" [formGroupName]="i">
    <!-- Select控件 -->
    <div class="clr-row">
      <clr-select-container>
        <select clrSelect formControlName="condition">
          <option value="">Select </option>
          <option value="custom">Custom</option>
          <option value="between">Between</option>
          <option value="lessThenEqual">Less then or Equal</option>
          <option value="moreThen">More then</option>
        </select>
      </clr-select-container>
    </div>

    <!-- 根据condition值显示对应Div -->
    <div class="clr-row" *ngIf="fieldGroup.get('condition').value === 'custom'">
      <div class="clr-col-4 ">
        <input clrInput placeholder="From Day" type="date" formControlName="customDayFrom" />
      </div>
      <div class="clr-col-4 ">
        <input clrInput placeholder="To Day" type="date" formControlName="customDayTo" />
      </div>
    </div>

    <div class="clr-row" *ngIf="fieldGroup.get('condition').value === 'between'">
      <div class="clr-col-4 ">
        <input clrInput placeholder="From Day" formControlName="customDayFrom" />
      </div>
      <div class="clr-col-4 ">
        <input clrInput placeholder="To Day" type="date" formControlName="customDayTo" />
      </div>
    </div>

    <div class="clr-row" *ngIf="fieldGroup.get('condition').value === 'lessThenEqual' || fieldGroup.get('condition').value === 'moreThen'">
      <div class="clr-col-4 ">
        <input clrInput placeholder="Day" formControlName="customDayFrom" />
      </div>
    </div>
  </div>
</div>

组件代码补充:

别忘了给你的FormGroup添加customDayFrom和customDayTo这两个控件,不然日期输入框会绑定失败:

addListFieldsFormGroup(name: string, value: string): FormGroup {
  return this.formBuilder.group({
    'condition': ['', [Validators.required]],
    'name': [name],
    'value': [value, [Validators.required]],
    'type': ['1', [Validators.required]],
    'operator': ['', [Validators.required]],
    'operand': ['', [Validators.required]],
    'customDayFrom': [''], // 添加日期控件
    'customDayTo': ['']    // 添加日期控件
  });
}

// 添加一个getter,方便模板访问FormArray
get listFieldArray(): FormArray {
  return this.form.get('listFieldArray') as FormArray;
}

方案二:订阅FormControl的valueChanges(适合需要额外逻辑的场景)

如果需要在condition值变化时做一些额外操作(比如清空不相关的日期输入框),可以在组件类里订阅每个FormGroup中condition控件的valueChanges事件。

组件代码示例:

// 新增添加FormArray项的方法
addListField(name: string = '', value: string = '') {
  const fieldGroup = this.addListFieldsFormGroup(name, value);
  
  // 订阅condition控件的值变化
  fieldGroup.get('condition').valueChanges.subscribe((conditionValue) => {
    // 示例:当选择非custom/between时,清空customDayTo的值
    if (conditionValue !== 'custom' && conditionValue !== 'between') {
      fieldGroup.get('customDayTo').setValue('');
    }
    // 这里可以添加其他业务逻辑,比如校验规则变更等
  });
  
  this.listFieldArray.push(fieldGroup);
}

模板部分和方案一一样就可以,这样既实现了条件显示,又能处理额外的业务逻辑。

为什么不能用[(ngModel)]?

Angular响应式表单的设计理念是通过FormControl/FormGroup/FormArray统一管理表单状态,混合使用[(ngModel)]会导致表单状态的双向绑定和响应式表单的单向数据流冲突,容易出现状态不一致的问题,所以官方在响应式表单场景下弃用了这种混合写法,推荐直接通过FormControl的value来控制视图。

内容的提问来源于stack exchange,提问作者Anand agrawal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:26:47