【问题标题】:Angular Reactive forms formgroupAngular 反应式表单表单组
【发布时间】:2021-01-12 21:10:31
【问题描述】:

我需要在同一个节点下为两个不同的数组创建一个 formControl,这样我就可以在给定的 Reactive 表单中添加和删除相应的嵌套节点。

预期的 JSON 格式:

{
  "title": null,
  "days": [
    {
      "date": null,
      "nodes": [
        {
          "type": "leg",
          "from": null,
          "to": null
        },
        {
          "type": "activity",
          "category": null
        }
      ]
    }
  ]
}

我已经实现了对日期和节点的控制,我可以分别添加和删除表单字段,但是我需要对节点下的类型腿和活动进行单独的控制。

这里有没有办法实现嵌套的formControl?

更新: 一个表单数组下需要两个表单组,请帮忙用HTML实现。

initX() {
    return this.fb.group({
      'date': [],
      'nodes': this.fb.array([
        this.initY(),
        this.initZ()
      ]),
    });
  }

  initY() {
    return this.fb.group({
      'type': ['leg'],
      'from': [],
      'to': []
    })
  }

  initZ() {
    return this.fb.group({
      'type': ['activity'],
      'category':[],
      'cost':[]
    })
  }

错误:找不到带有路径的控件:'days -> 0 -> nodes -> 1 -> from'

可以在这里找到示例代码的stackblitz:https://stackblitz.com/edit/angular-ivy-fkgxrr

【问题讨论】:

  • 不清楚您所说的“我需要对节点下的类型腿和活动进行单独的控件”是什么意思,因为在您的示例中,您已经有两种不同的方法返回了不同的结构。
  • 嗨@FrancescoColamonici 我能够在JSON 中进行格式化,但是在HTML 下的formArray 中没有任何控件。日期和节点分别使用单独的控件循环,我希望对 Leg 和 Activities 执行相同的操作,但是在节点下。
  • @FrancescoColamonici 我更新了我的描述。

标签: javascript angular angular-reactive-forms angular-forms angular-formbuilder


【解决方案1】:

我知道这可能不是一个完整的响应,因为嵌套 FormArrays 的工作示例需要一些时间,但我很确定你会发现这篇文章有趣且有用(这在很多情况下帮助了我,比如这):

【讨论】:

    【解决方案2】:

    好吧,在我的另一个答案中,“节点”数组就像

    [
     {"type": "leg","from": null,"to": null,"category": null}
     {"type": "leg","from": null,"to": null,"category": null}
    ]
    

    formArray 需要所有元素具有相同的属性

    问题:nodes只是一个包含两个元素的数组(一个用于控制Leg,另一个用于控制类别)?

    在这种情况下,days 是一个 formArray,每个元素是一个带有两个 peoperies 的 formGroup,其中一个是具有两个元素的 一个数组(不是 formArray)

    form=new FormGroup({
      title:new FormControl()
      days:new FormArray([
         date:new FormControl(),
         nodes:[new FormGroup({...}),new FormGroup({..})]
      ])
    })
    

    在这种情况下,你可以拥有三个 getter

    get days():FormArray
    {
        return this.formGroup.get('days') as FormArray;
    }
    get leg(index)
    {
        return this.days.at(i).get('nodes')[0] as FormGroup
    }
    get category(index)
    {
        return this.days.at(i).get('nodes')[1] as FormGroup
    }
    

    并在 div 中直接使用[formGroup],例如

    <div [formGroup]="category[i]">
       <input formControlName="from">
       ...
    </div>
    

    否则我无法理解你的 json

    【讨论】:

      【解决方案3】:

      keethama,一步一步来。你在 formArray 中有一个 formArray,所以创建两个返回 formArray 的函数

        get days():FormArray
        {
          return this.formGroup.get('days') as FormArray;
        }
        getNodes(i:number):FormArray
        {
          return this.days.at(i).get('nodes') as FormArray
        }
      

      那么,创建表单需要使用三个函数:

        createForm(data:any)
        {
          data=data || {title:null,days:null}
          return new FormGroup({
            title:new FormControl(data.title),
            days:data.days?
                 new FormArray(data.days.map(d=>this.createDays(d))):
                 new FormArray([])
            
          })
        }
        createDays(data:any=null)
        {
          data=data || {date:null,nodes:null}
          return new FormGroup({
              date:new FormControl(data.date),
              nodes:data.nodes?
                    new FormArray(data.nodes.map(x=>this.createNodes(x))):
                    new FormArray([])
          })
        }
        createNodes(data:any=null)
        {
          data={type:null,from:null,to:null,category:null,...data}
          return new FormGroup({
            type: new FormControl(data.type),
            from: new FormControl(data.from),
            to: new FormControl(data.to),
            category: new FormControl(data.category)
          })
        }
      

      好吧,现在看看.html

      <form *ngIf="formGroup" [formGroup]="formGroup">
        title:<input formControlName="title">
        <div formArrayName="days">
          <div *ngFor="let groupDays of days.controls;let i=index" [formGroupName]="i">
              date:<input formControlName="date">
              <div formArrayName="nodes">
                <div *ngFor="let groupnodes of getNodes(i).controls;let j=index" [formGroupName]="j">        
                  type:<input formControlName="type"><br/>
              from:<input formControlName="from"><br/>
      
              to:<input formControlName="to"><br/>
              category:<input formControlName="category">
                </div>
              </div>
          </div>
        </div>
      </form>
      

      在 ngOnInit 中

      this.formGroup=this.createForm(this.data)
      

      看看如果你想在你使用的索引索引中的节点上添加一个新节点

         this.getNodes(index).push(this.createNodes())
      

      并在 days 数组中添加一个新节点

         this.days.push(this.createDays())
      

      incomplete stackblitz

      【讨论】:

      • 嗨.. 感谢您的示例代码,但是这里的代码仍然具有相同的 formArray 和所有节点的控件。我需要在节点下分别控制 Leg 和 Activity。有什么可行的建议吗?
      • nodes 只是一个包含两个元素的数组(一个用于控制腿,另一个用于控制类别)?如果属实,请参阅我的另一个答案,否则我无法理解您的 json。
      【解决方案4】:

      尝试使用两种方式的数据绑定。这将简化您的流程。

      例如:

      <input type="text" name="name" [(ngModel)]="model.name">
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-04
        • 2019-02-01
        • 2017-11-17
        • 2020-05-05
        • 2019-05-04
        相关资源
        最近更新 更多