【问题标题】:How can I generate FormControls dynamically inside a FormGroup?如何在 FormGroup 中动态生成 FormControl?
【发布时间】:2021-02-04 13:48:31
【问题描述】:

我从数据库接收到一个对象,其中包含一些具有以下格式的元素:

info = [{
    idcentro: "8227",
    namecentro: "Centro Paris", 
    address: "C/ Paris, 127",
    dias: [
      {
        dia: "0",
        horafinal: "06:00",
        horainicio: "17:00",
        salas: [
          {
            id: 0,
            nombre: "sala 1",
            intervalos: [
                ["09:00", "12:30", "10"],
                ["13:00", "21:30", "20"]
            ]
          }
        ]
      },
      {
        dia: "1",
        horafinal: "09:00",
        horainicio: "16:30",
        salas: [
          {
            id: 0,
            nombre: "sala 1",
            intervalos: [
                ["09:00", "12:30", "10"]
            ]
          },
          {
            id: 1,
            nombre: "sala 2",
            intervalos: [
                ["09:00", "20:30", "20"]
            ]
          }
        ]
      },
      {
        dia: "2",
        horafinal: "09:00",
        horainicio: "20:30",
        salas: [
          {
            id: 0,
            nombre: "sala 1",
            intervalos: [
                ["09:00", "12:30", "10"],
                ["12:45", "18:30", "15"]
            ]
          },
          {
            id: 1,
            nombre: "sala 2",
            intervalos: [
                ["09:00", "20:30", "20"]
            ]
          }
        ]
      }
    ]
  }];

为了使用这些“dias”数组并包含输入以在用户想要的情况下修改每个值,我手动创建了一个 FormGroup,其中包含每天的 formControl(实际对象最多包含 8 天) .

    this.openingHoursForm = new FormGroup({
      day0OpeningTime: new FormControl(""),
      day0ClosingTime: new FormControl(""),
      day1OpeningTime: new FormControl(""),
      day1ClosingTime: new FormControl(""),
      day2OpeningTime: new FormControl(""),
      day2ClosingTime: new FormControl(""),
      day3OpeningTime: new FormControl(""),
      day3ClosingTime: new FormControl(""),
      day4OpeningTime: new FormControl(""),
      day4ClosingTime: new FormControl(""),
      day5OpeningTime: new FormControl(""),
      day5ClosingTime: new FormControl(""),
      day6OpeningTime: new FormControl(""),
      day6ClosingTime: new FormControl(""),
      day7OpeningTime: new FormControl(""),
      day7ClosingTime: new FormControl(""),
      day8OpeningTime: new FormControl(""),
      day8ClosingTime: new FormControl("")
    });

然后,在 HTML 中,我为这些 formControlNames 中的每一个创建两个输入:

<div class="dayOpeningHours" title="">
  <div>Day 0</div>
   <div class="opens">
     <label for="">De:
       <input class="form-control" type="time" formControlName="day0OpeningTime" name="day0OpeningTime">
     </label>
   </div>
   <div class="closes">
     <label for="">A:
       <input class="form-control" formControlName="day0ClosingTime" name="day0ClosingTime">
     </label>
   </div>
</div>

如您所见,这变得非常难以维护。我试图通过循环遍历“dias”数组的每个“dia”来动态创建标记(在 html 中)和 formControlNames(在 ts 中),但我没有取得任何成果。

有没有一种方法可以在同一个 formGroup 中生成 HTML 和这些表单控件的声明?我一直在阅读有关 FormArray 和 AbstractControl 的内容,但我无法真正理解如何将其应用到我的代码中。

有人可以帮助我或给我一些提示以找到正确的文档吗?

谢谢

【问题讨论】:

    标签: javascript angular typescript angular-directive dynamic-arrays


    【解决方案1】:

    更好的选择是改用FormArray。你也可以从@angular/forms注入FormBuilder

    见下文

    constructor (private fb: FormBuilder) { }
    diasForm = this.fb.group({
      openingHours: this.fb.array([])
    })
    get openingHours (): FormArray {
      return this.diasForm.get('openingHours') as FormArray;
    }
    
    

    下一个任务是创建表单 假设我们有 dias 作为一个数组

    dias = [
          {
            dia: "0",
            horafinal: "06:00",
            horainicio: "17:00",
          },
          {
            dia: "1",
            horafinal: "06:00",
            horainicio: "17:00",
          },
          ...
    ]
    
    

    为简单起见,我删除了其他属性 在ngOnInit我们可以设置表单的值

    ngOnInit() {
      this.dias.forEach(dia => {
        this.openingHours.push(
          this.fb.group({
            horafinal: [dia.horafinal, []],
            horainicio: [dia.horainicio, []]
          })
        )
      })
    }
    
    

    在 HTML 中

    <form [formGroup]='diasForm'>
      <div formArrayName='openingHours'>
        <div *ngFor='let item of openingHours.controls; let i = index' 
           [formGroupName]='i'>
             <input formControlName='horafinal' />
             <input formControlName='horainicio' />
        </div>
      </div>
    </form>
    

    上面应该和我们formGroup的结构相匹配

    diasForm( [formGroup] ) ---&gt; openingHours(formArray) ---&gt; i ( [formGroup] ) ---&gt; horafinal(formControl)

    请看this demo on stackblitz

    这样你可以有一个动态的天数

    【讨论】:

    • 感谢欧文的回答!但是....我将如何在 html 端实现它?
    • 我添加了一个演示
    【解决方案2】:

    这是一个大而复杂的对象,但是控制一个json对象的“方式”总是一样的:简单的属性是FormControl,数组是FormArrays,我们使用FormGroup对控件进行分组。

    那么仔细,做四个函数来创建表单

      createForm(data: any = null) {
        data = data || {idcentro: null,namecentro: null,address: null,dias: null};
        return new FormGroup({
          idcentro: new FormControl(data.idcentro),
          namecentro: new FormControl(data.namecentro),
          address: new FormControl(data.address),
          dias: new FormArray(
            data.dias ? data.dias.map(x => this.createFormDias(x)) : []
          )
        });
      }
      createFormDias(data: any = null) {
        data = data || {dia: null,horafinal: null,horainicio: null,salas: null};
        return new FormGroup({
          dia: new FormControl(data.dia),
          horafinal: new FormControl(data.horafinal),
          horainicio: new FormControl(data.horainicio),
          salas: new FormArray(
            data.salas ? data.salas.map(x => this.createFormSalas(x)) : []
          )
        });
      }
    createFormSalas(data: any = null) {
        data = data || { id: null, nombre: null, intervalos: null };
        return new FormGroup({
          id: new FormControl(data.id),
          nombre: new FormControl(data.nombre),
          intervalos:new FormArray(
            data.intervalos?this.createFormIntervalos(data.intervalos):[])
        });
      }
      createFormIntervalos(data:any=null)
      {
        return data.map(x=>new FormArray(x.map(y=>new FormControl(y))))
      }
    

    还有四个函数可以得到formArrays

      get diasArray()
      {
        return this.form.get('dias') as FormArray
      }
      getSalas(index)
      {
        return this.diasArray.at(index).get('salas') as FormArray
      }
      getIntervalos(index1,index2)
      {
        return this.getSalas(index1).at(index2).get('intervalos') as FormArray
      }
      getHoras(index1,index2,index3)
      {
        return this.getIntervalos(index1,index2).at(index3) as FormArray
      }
    

    要在 .html 中进行控制,您需要考虑 FormArray 何时是 FormGroups 的 FormArray 以及何时是 FormControls 的 FormArray

    <form [formGroup]="form">
      <div>idcentro:<input formControlName="idcentro" /></div>
      <div>namecentro:<input formControlName="namecentro" /></div>
      <div>address:<input formControlName="address" /></div>
      <div formArrayName="dias">
        <div
          *ngFor="let grDias of diasArray.controls;let i=index"
          [formGroupName]="i"
        >
          <div>dia:<input formControlName="dia" /></div>
          <div>horafinal:<input formControlName="horafinal" /></div>
          <div>horainicio:<input formControlName="horainicio" /></div>
          <div formArrayName="salas">
            <div
              *ngFor="let grSalas of getSalas(i).controls;let j=index"
              [formGroupName]="j"
            >
              <div>id:<input formControlName="id" /></div>
              <div>nombre:<input formControlName="nombre" /></div>
              <div formArrayName="intervalos">
                <div
                  *ngFor="let grIntervalos of getIntervalos(i,j).controls;let k=index"
                >
                  <div [formArrayName]="k">
                    <div *ngFor="let grHoras of getHoras(i,j,k).controls;let m=index">
                      <input [formControlName]="m">
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </form>
    

    ugly stackblitz

    看到我们使用的FormGroup的FormArray

    <div formGroupName="nameOfArray">
      <div *ngFor="let group of formArray.controls;let i=index" [formGroupName]="i">
         ..here..
         <input formControlName="controlName">
      </div>
    </div>
    

    还有一个 FormGroup 的 FormControls

    <div formGroupName="nameOfArray">
      <div *ngFor="let group of formArray.controls;let i=index" >
         <input [formControlName]="i">
      </div>
    </div>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-27
      • 1970-01-01
      • 1970-01-01
      • 2019-07-28
      • 2018-01-06
      • 2017-06-09
      • 2021-05-12
      相关资源
      最近更新 更多