首页 > 解决方案 > 如何根据 Angular Reactive Forms 重新分配嵌套数组键?

问题描述

我正在努力为 Angular Reactive Forms 重新创建嵌套数组。

现有的嵌套数组。

nestedArray = [{
    id:'abc',
    required:true,
    children:[{
        id:"bcd",
        parentId:"abc",
        required:true,
        children:[{
            id:"cde",
            parentId:"bcd",
            required:false,
            children:[{
                id:"def",
                parentId:"cde",
                required:true,
                children:[{
                    id:"efg",
                    parentId:"def",
                    required:false,                        
                }]
            },
            {
                id: "xyz",
                parentId: "cde",
                required: true,
            }]
        }]
    }]
}]

为Angular Reactive Forms重新创建这个数组

nestedArray= this.fb.group({
    abc: [''],
    bcd: this.fb.group({
      cde: [''],
      efg: [''],
    }),
  });

上面的数组不正确,正在寻找以 Angular Reactive Form 创建子代的正确方法。

谢谢

标签: arraysangularangular-forms

解决方案


您需要创建一个返回 FormControl 或 FormGroup 的递归函数

  form = new FormArray(this.nestedArray.map(x=>{
    const group=new FormGroup({})
    group.addControl(x.id,this.getGroup(x))
    return group
    }));

  getGroup(data: any) {
    if (!data.children)
      return new FormControl()
    const group = new FormGroup({});
    if (data.children) {
      
      data.children.forEach(x=>{
        group.addControl(x.id,this.getGroup(x))
      })
    }
    return group;
  }

stackblitz

更新真的答案是错误的,因为我们没有对“父母”的形式控制。功能必须像

  form = new FormArray(this.nestedArray.map(x=>this.getGroup(x)))
  getGroup(data: any) {
    if (!data.children)
    { 
      return new FormControl)
    }
    const group = new FormGroup({});
    group.addControl(data.id,new FormControl())
    if (data.children) {
      
      data.children.forEach(x=>{
        group.addControl(x.id,this.getGroup(x))
      })
    }
    return group;
  }

好吧,问题是如何控制这种疯狂的形式。我们可以尝试创建一个“递归模板”,但我认为这是另一种更好的方法。想象一下,你有一个元素数组,每个元素都有三个属性:“index”、“label”和“control”。而control是对我们表单的FormControl的引用。然后我们可以构造一个 .html 之类的

<div *ngFor="let item of controls">
    <span [style.margin-left]="item.index*10+'px'">{{item.label}}</span>
    <input [formControl]="item.control">
    <span *ngIf="item.control.errors?.required">*</span>
</div>

容易吗?直接使用[formControl]and item.control.errorsoritem.control.touched

好吧,为此首先声明一个空数组

  controls:any[]=[];

并更改功能,因此我们分两步添加组:1.-创建 formControl,2.-添加到组中,第三步是向我们的数组添加一个带有 {label,control 和“index”}的对象。当我们有一个递归函数想知道递归的“索引”时,这是很典型的。

  //we pass as index 0 at first
  form = new FormArray(this.nestedArray.map(x=>this.getGroup(x,0)))
  getGroup(data: any,index:number) {
    if (!data.children)
    { 
      //create the control
      const control=new FormControl('',data.required?Validators.required:null)

      //add to the array this.controls
      this.controls.push({control:control,label:data.id,index:index})

      //return control
      return control
    }
    const group = new FormGroup({});
    index++
    //create the control
    const control=new FormControl('',data.required?Validators.required:null)

    //add to the array this.controls
    this.controls.push({control:control,label:data.id,index:index})

    //add the control to the group
    group.addControl(data.id,control)

    if (data.children) {
      data.children.forEach(x=>{
        group.addControl(x.id,this.getGroup(x,index++))
      })
    }
    return group;
  }

好吧,在 stackblitz 中,将属性“value”添加到我们的复杂对象中,以展示如何做到这一点,我们使用“id”作为“标签”——也许我们的复杂对象需要一个新的属性标签——


推荐阅读