简体   繁体   English

如何将数据绑定到深层嵌套 arrays? Angular Forms

[英]How to Data bind to deep nested arrays? Angular Forms

Background:背景:

I am trying to make a three-layered form front-end, the user should be able to fill out the basic details as well as the list object with the title.我正在尝试制作一个三层表单前端,用户应该能够填写基本详细信息以及带有标题的列表 object。 The list in its entirety needs to be an array the user can add to make a new list in addition to adding individual nested list items:整个列表需要是一个数组,除了添加单个嵌套列表项之外,用户还可以添加以创建新列表:

I am using Angular Form Groups and Form Arrays to try and achieve this:我正在使用 Angular Form Groups 和 Form Arrays 来尝试实现此目的:

Desired Form Inputs / Data Structure :所需的表单输入/数据结构

This is the data structure I want to achieve:这是我要实现的数据结构:

{ "name": "", "email": "", "list": 
[ { "list_title": "", 
"list_items": [ { "list_item_1": {}, "list_item_2": {} } ] } 
] }

Above you can see the desired data to be captured.在上方您可以看到要捕获的所需数据。 In the outer form, you can see three fields.在外部形式中,您可以看到三个字段。 I would like to nest list titles and list items within the list field.我想在列表字段中嵌套列表标题和列表项。 List items is another array nested within that.列表项是嵌套在其中的另一个数组。 The idea is to get to a position where the user can add items and list objects with new items ect..,这个想法是到达 position ,用户可以在其中添加项目并列出带有新项目的对象等..,

Code so far到目前为止的代码

I have decided to do this in a two components and have am able to access the outer items but struggling to access my inner array to data bind.我已经决定在两个组件中执行此操作并且能够访问外部项目但努力访问我的内部数组以进行数据绑定。

Parent-comp.html :父组件 html

<p>form-comp works!</p>
<div class="form-container">
  <form (ngSubmit)="submit()" [formGroup]="myForm">
    <h1>User Registration</h1>
    <div class="form-group">
      <label for="firstname"></label>`
      <input type="text" placeholder="First Name" formControlName="name" />
      <input type="text" placeholder="Surname" formControlName="email" />
      <br />
      <div formArrayName="list">
        <ng-container *ngFor="let myList of listArray.controls; index as i">
          <div [formGroupName]="i">
            <input
              type="text"
              name="firstname"
              placeholder="List Title"
              formControlName="name"
              formControlName="list_title"
            />
            <br />
          </div>
        
          <!-- // map items here -->
          <app-products></app-products>


        </ng-container>

        <button (click)="addList()">Add List</button>
      </div>
      <button type="submit">Submit</button>
    </div>

    <br />
    <div class="form-check">
      {{ myForm.value | json }}
      <br />
      {{ myForm.valid | json }}
    </div>
  </form>
</div> 

Parent-comp-tsx父补偿 tsx

export class FormCompComponent implements OnInit {
  myForm!: FormGroup;

  constructor (private fb : FormBuilder) {

  }

  ngOnInit(): void {
    this.myForm = new FormGroup({
      name: new FormControl('', Validators.required),
      email: new FormControl('', Validators.required),
      list: new FormArray([this.initListFormGroup()]),

    });

  }

  addList() {
    this.listArray.push(this.initListFormGroup());
  }

  initListFormGroup() {
    return new FormGroup({
      list_title: new FormControl('', Validators.required),
      list_items: new FormArray([ ProductsComponent.addListItem()])
    });
  }

  get listArray() {
    return this.myForm.get('list') as FormArray;
  }

  submit() {
    console.log(this.myForm.value);
  }
}

Thhrough the code above I am able to push new list parent groups to the array and data bind by looping through these fine.通过上面的代码,我可以将新的列表父组推送到数组,并通过循环遍历这些数据来绑定数据。 I am also calling a static method on the child component to generate a new item with:我还在子组件上调用 static 方法来生成一个新项目:

ProductsComponent.addListItem()

Child-comp.html :子组件 html

<form [formGroup]="childForm">
<input type="text" name="list_item" placeholder="List Item" formControlName="name" formControlName="list_item_1" />
</form>

export class ProductsComponent {出口 class ProductsComponent {

  @Input()
  public childForm!: FormGroup;

  constructor() {}
  static addListItem(): FormGroup {
    return new FormGroup({
      list_item_1: new FormGroup(''),
      list_item_2: new FormGroup(''),
    });
  }
}

So far I am able to generate my data structure and can see this on screen when I return myForm.value However struggling to map over the child array:到目前为止,我能够生成我的数据结构,并且当我返回myForm.value时可以在屏幕上看到它但是在子数组上努力达到 map:

      <!-- // map items here -->
          <app-products></app-products>

Above is where I believe I need to map over the inner array but not sure what the equivalent function would be to return that Array since its essentially buried.上面是我认为我需要在内部数组上使用 map 的地方,但不确定返回该数组的等效 function 是什么,因为它基本上被埋没了。

Here is the reference tutorial at the step where my use case begins to depart:这是我的用例开始离开的步骤的参考教程:

https://youtu.be/DEuTcG8DxUI?t=652 https://youtu.be/DEuTcG8DxUI?t=652

Please let me know if this question makes sense I am eager to solve it, thank you!如果这个问题有意义,请告诉我,我很想解决它,谢谢!

This may look complex but the concept is similar that what you work with FormArray in the parent form and you need to ensure that you need to provide the FormGroup index for rendering the nested object in the array.这可能看起来很复杂,但概念与您在父表单中使用FormArray的概念类似,您需要确保需要提供FormGroup索引以呈现数组中的嵌套 object。

<!-- // map items here -->
<ng-container formArrayName="list_items">
  <ng-container
    *ngFor="
      let listItem of getListItemArrayFromList(i).controls;
      index as j
    "
  >
    <app-products [childForm]="asListItemFormGroup(listItem)"></app-products>
  </ng-container>
</ng-container>

<button (click)="addListItem(i)">Add List Item</button>
getListItemArrayFromList(i: number) {
  return (this.listArray.get(`${i}`) as FormGroup).get(
    'list_items'
  ) as FormArray;
}

asListItemFormGroup(listItem: AbstractControl) {
  return listItem as FormGroup;
}

addListItem(formGroupIndex: number) {
  this.getListItemArrayFromList(formGroupIndex).push(
    ProductsComponent.addListItem()
  );
}

Note that based on your provided data, list_item_1 and list_item_2 are objects, hence you should use formGroupName attribute instead of formControlName attribute, and create a FormGroup template with FormControl (s).请注意,根据您提供的数据, list_item_1list_item_2是对象,因此您应该使用formGroupName属性而不是formControlName属性,并使用FormControl (s) 创建一个FormGroup模板。

<form [formGroup]="childForm">
  <input
    type="text"
    name="list_item"
    placeholder="List Item 1"
    formGroupName="list_item_1"
  />

  <input
    type="text"
    name="list_item"
    placeholder="List Item 2"
    formGroupName="list_item_2"
  />
</form>

Demo @ StackBlitz 演示 @ StackBlitz

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM