Я понял концепцию рекурсивных элементов (древовидное представление) снизу.

Ссылка 1

В моем случае я хочу использовать его с формами; скажем, простой рекурсивный ввод текста. Структура формы JSON приведена ниже.

Структура JSON

Я подготовил приведенный ниже код. Я получаю ошибку Превышен максимальный размер стека вызовов , выполнив приведенный ниже код.

Ниже мой файл 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);
}
}
7
Techno Crave 24 Окт 2018 в 07:52

2 ответа

Лучший ответ

Фактически, ответ Бхавика Пателя решит проблему с ошибкой:

Превышен максимальный размер стека вызовов

Но ваши привязки форм не будут работать должным образом из-за того, как работают реактивные формы 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

11
yurzui 14 Ноя 2018 в 10:08

В ваш 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-кода. Он должен генерироваться динамически.

2
Bhavik Patel 14 Ноя 2018 в 07:06
52961297