以 angular 反应形式显示条件输入框

Display input box on condition in angular reactive form

我正在制作 angular 6 个应用程序,我正在使用 angular 反应形式。

Html:

<form [formGroup]="form">

    <h2>Click the add button below</h2>
    <button (click)="addCreds()">Add</button>
        <div formArrayName="credentials" *ngFor="let creds of form.controls.credentials?.value; let i = index">
          <div [formGroupName]="i" style="display: flex">
            <select (ngModelChange)="changeAction($event)" formControlName="action">
              <option *ngFor="let option of options" value="{{option.key}}"> {{option.value}} </option>
            </select>
            <input placeholder="Name" formControlName="name">
            <div *ngIf="showLabel">
            <input placeholder="Label" formControlName="label">
            </div>
          </div>
        </div>

    </form>

    <pre>
      {{ form ?.value | json }}
    </pre>

Ts:

  form: FormGroup;
  showLabel: boolean = false;

  options : any = [ 
    { "key" : "set", "value": "Set" },
    { "key" : "wait", "value": "Wait" },
    { "key" : "go", "value": "Go" }   
    ]

  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({
      credentials: this.fb.array([]),
    });
  }

  addCreds() {
    const creds = this.form.controls.credentials as FormArray;
    creds.push(this.fb.group({
      action: '',
      name: '',
      label: ''
    }));
  }

  changeAction(e) {
    if(e === "set" || e === "go") {
      this.showLabel = true;
    } else {
      this.showLabel = false;
    }
  }

工作 stackblitz: https://stackblitz.com/edit/angular-form-array-example-yksojj

在这个给定的示例中,将有一个添加按钮,单击该按钮后,您将获得一个值为 set,wait,goselect-box 和一个名为 name 的输入。单击添加按钮后,将添加相同的行并在数组中形成每个对象。

您还可以在标签 html 中看到 if 条件,

<div *ngIf="showLabel">
  <input placeholder="Label" formControlName="label">
</div>

我需要的东西在select框中,如果我选择set or go那么标签需要显示,否则不应该显示我写的,

  changeAction(e) {
    if(e === "set" || e === "go") {
      this.showLabel = true;
    } else {
      this.showLabel = false;
    }
  }

为了清楚起见 如果用户点击了三次添加按钮,那么仅下拉菜单和名称字段就需要显示三次,而如果用户 select s 下拉列表中的值为 set 或 go 然后标签输入需要单独显示到 特定行,其中下拉列表设置了值并 go.. 如果 selection 是 wait 那么对于下拉值为 wait 的行不应该有标签框。

请帮助我达到预期的结果..

this.showLabel

这个变量的范围是你的整个组件。因此,打开或关闭它会显示和隐藏所有输入。

您需要一个每行值(在您的界面中creds.showLabel),或者在您的模板中使用它:

*ngIf="['set','go'].includes(creds.action)"

Updated Stackblitz

顺便说一句,这个:

changeAction(e) {
    if(e === "set" || e === "go") {
      this.showLabel = true;
    } else {
      this.showLabel = false;
    }
  }

这样写比较优雅:

changeAction(e) {
    this.showLabel = ['set','go'].includes(e)
}

或者这样:

changeAction(e) {
    this.showLabel = e in ['set','go']
}

好吧,Jeremy's 非常好,强制使用 platform/language 提供的大部分原生 API,但是,这里有一个 传统的 方法来了解对象的实际流程和范围等...

根本原因: 显示隐藏字段在组件范围内是全局的,而不是在每个 formgroup 级别。因此,更改单个值并用于所有值,将影响到所有值。

解法:

  1. 使用 Jeremy's 以获得干净的编码和不易出错的代码。

  2. 管理一个变量数组,它将处理 sho/hide 每个表单组的详细信息。

在下面的答案中,添加了一些注释以便于理解,并添加了console.log以查看到底发生了什么。此外,还尝试了在 *ngFor 中创建的索引 i,并展示了将来如何使用这些东西。

import { Component } from '@angular/core';
import { FormControl, FormGroup, FormArray, FormBuilder } from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: 'app.component.html',
})
export class AppComponent  {
  form: FormGroup ;
  showLabel = [];
  creds : FormArray; 
  options : any = [ 
    { "key" : "set", "value": "Set" },
    { "key" : "wait", "value": "Wait" },
    { "key" : "go", "value": "Go" }   
    ]

  constructor(private fb: FormBuilder) {
    
    this.form = this.fb.group({
      credentials: this.fb.array([]),
    });
    this.creds = this.form.controls.credentials as FormArray;
  }

  addCreds() {
    
    this.creds.push(this.fb.group({
      action: '',
      name: '',
      label: ''
    }));
    // every time adding new foem grp, adding lable show/hide data also.
  this.showLabel.push(false);

  }

  changeAction(e, i) {
    //every time input clikced, managing show/hide for that particular data also
    console.log("iii", i, e.target.value);
    if( e.target.value == "set" ||  e.target.value == "go") {
      this.showLabel[i] = true;
    } else {
      this.showLabel[i] = false;
    }
  }

}
<form [formGroup]="form">

 <h2>Click the add button below</h2>
 <button (click)="addCreds()">Add</button>
        <div formArrayName="credentials" *ngFor="let creds of form.controls.credentials?.value; let i = index">
          <div [formGroupName]="i" >
            <select (change)="changeAction($event, i)" formControlName="action">
              <option *ngFor="let option of options" value="{{option.key}}"> {{option.value}} </option>
            </select>
            <input placeholder="Name" formControlName="name">
            <div *ngIf="showLabel[i]">
            <input placeholder="Label" formControlName="label">
            </div>
          </div>
        </div>

    </form>

    <pre>
      {{ form ?.value | json }}
    </pre>

See live stackblitz working code

注意:传统 是指这里.. 就像我们每次做的那样,即我们自己处理我们的问题并创造新的问题来解决。 这不是传统。 :P

如果您将 disabled:true 属性 添加到 formControl,它将从 formGroup 中排除 fromControl 然后您可以手动启用 formControl

creds.push(this.fb.group({
      action: '',
      name: '',
      label: {disabled:true, value: ""}
    }));

然后使用启用方法启用

changeAction(e,index) {
    if(e === "set" || e === "go") {
      this.showLabel = true;     
     this.form.get('credentials').at(index).get('label').enable();

    } else {
      this.showLabel = false;
      this.form.get('credentials').at(index).get('label').disable();
    }
  }

示例:https://stackblitz.com/edit/angular-form-array-example-5buwyr

请不要使用 (ngModelChange)changeAction($event) 来获取数组中控件的值 - 那么,ngModelChange 用于模板驱动形式, 反应形式。

首先更改您的表单,使用带有 formArrayName="credentials" 的 div 和内部 div *ngFor="let creds of form.get('credentials').controls[=18 创建表单=]

    <!--a div with formArrayName--->
    <div formArrayName="credentials" >
      <!--a div *ngFor over "controls", in this div don't forget formGroupName-->
      <div *ngFor="let creds of form.get('credentials').controls; let i = index" 
          [formGroupName]="i" style="display: flex">
          <select formControlName="action">
             <option *ngFor="let option of options" value="{{option.key}}">
               {{option.value}} 
             </option>
          </select>
          <input placeholder="Name" formControlName="name">
          <div *ngIf="??????????????">
             <input placeholder="Label" formControlName="label">
          </div>
      </div>
    </div>

好了,现在的条件。要获得 "action" 的值,您可以使用

form.get('credentials').at(i).value.action
//or, better
creds.value.action

所以,你的 div 变成了

<div *ngIf="creds.value.action=='set' ||
      creds.value.action=='go'">
  <input placeholder="Label" formControlName="label">
</div>

这种方法可以避免您的 .ts 中出现不必要的代码。