在角度6中使用反应形式的递归形式(树形视图)

时间:2018-10-24 04:52:27

标签: angular angular6

我从下面了解了递归元素(树视图)的概念。

Link 1

就我而言,我想将其与表格一起使用;假设递归地输入简单文本。表单的JSON结构如下。

JOSN Structure

我已经准备了以下代码。通过执行以下代码,我收到超出最大调用堆栈大小的错误。

下面是我的 component.html 文件。

<form [formGroup]="testForm" (ngSubmit)="onSubmit()">
    <div formArrayName="element">
        <ng-template #recursiveList let-list>       
              <div *ngFor="let item of testForm.get('element').controls;let i=index;">     
                  <div [formGroupName]="i">
                    <input type="text" formControlName="type">
                  </div> 
                  <!-- {{item.get('element')?.controls?.length}} -->
                  <div *ngIf="item.get('element')?.controls?.length > 0">          
                    <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: item.get('element').controls }"></ng-container>
                  </div>
              </div>          
        </ng-template>
        <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: testForm.get('element').controls }"></ng-container>
    </div>     

这是 component.ts 文件。

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

@Component({
    selector: 'app-test',
    templateUrl: './test.component.html',
    styleUrls: [
      './test.component.scss'
    ]
  })
export class TestComponent implements OnInit{
    testForm:FormGroup;
    element:any;

constructor(private formBuilder: FormBuilder) { }
ngOnInit() {

this.testForm=this.formBuilder.group({
  element:this.formBuilder.array([
    this.formBuilder.group({
      type:'',
      element:this.formBuilder.array([
        this.formBuilder.group({
          type:'',
          element:this.formBuilder.array([                
          ])
        })
      ])        
    })
  ])
})
}

onSubmit() {       
    console.log(this.testForm.value);
}
}

2 个答案:

答案 0 :(得分:4)

实际上,Bhavik Patel的答案将解决以下错误问题:

  

超出了最大调用堆栈大小

但是由于Angular反应性表单的工作方式,您的表单绑定无法正常工作。 它依赖于依赖注入树,此模板看起来像:

FormGroup(testForm)
  |__ FormArrayName('element')
           |___ FormGroupName('0')
           |     ....
           |___ FormGroupName(n)

您将始终仅在顶级控件上获得更新。

要解决此问题,您可以定义一些前缀,这些前缀将在嵌入式视图中更新。然后使用该前缀在树的每个级别上定义formGroup

<form class="tree" [formGroup]="testForm" (ngSubmit)="onSubmit()">
  <ng-template #recursiveList let-controls let-prefix="prefix">
    <ng-container *ngFor="let item of controls; let i = index">
      <div class="tree-item" [formGroup]="testForm.get(prefix + i)">
        <input type="text" formControlName="type">
      </div>
      <div class="sub-tree" *ngIf="item.get('element')?.controls?.length">
        <ng-container
          *ngTemplateOutlet="recursiveList; context:{ $implicit: item.get('element').controls, prefix: prefix + i + '.element.'  }"></ng-container>
      </div>
    </ng-container>
  </ng-template>
  <ng-container
    *ngTemplateOutlet="recursiveList; context:{ $implicit: testForm.get('element').controls, prefix: 'element.' }"></ng-container>
</form>

Ng-run Example

答案 1 :(得分:2)

寻找元素列表而不是列表属性本身时,HTML代码中有一些更改。

这是解决问题后的更新代码。

component.html

 <form [formGroup]="testForm" (ngSubmit)="onSubmit()">
  <div formArrayName="element">
      <ng-template #recursiveList let-element>
            <div *ngFor="let item of element;let i=index;">
                <div [formGroupName]="i">
                  <input type="text" formControlName="type">
                </div>
                <!-- {{item.get('element')?.controls?.length}} -->
                <div *ngIf="item.get('element')?.controls?.length > 0">
                  <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: item.get('element').controls }"></ng-container>
                </div>
            </div>
      </ng-template>
      <ng-container *ngTemplateOutlet="recursiveList; context:{ $implicit: testForm.get('element').controls }"></ng-container>
  </div>
 </form>

P.S .:当然,您也应该重构您的ts代码。它应该是动态生成的。