ReactiveForms с динамическими c рекурсивными шаблонами - PullRequest
8 голосов
/ 16 января 2020

Вот моя проблема.

Онлайн Пример проблемы

У меня есть динамо c JSON, которое мне нужно преобразовать в форму. Итак, я использовал реактивные формы и, пройдя по всем свойствам JSON, создаю FormGroup или FormControl следующим образом:

sampleJson ={prop1:"value1", prop2: "value2",...}

...

  myForm: FormGroup;
  myKeys=[];
    ...

  ngOnInit() {
    this.myForm = this.getFormGroupControls(this.sampleJson, this.myKeys);

  }

getFormGroupControls(json:any,keys): FormGroup{
    let controls = {};
    let value = {};

    for (let key in json) {
      if (json.hasOwnProperty(key)) {

        value = json[key];
        if (value instanceof Object && value.constructor === Object) {

          keys.push({"key":key,children:[]});
          controls[key] = this.getFormGroupControls(value,keys[keys.length-1].children);
        } else {

          keys.push({"key":key,children:[]});
          controls[key] = new FormControl(value);

        }
      }
    }

    return new FormGroup(controls);
  }

После этого я использую рекурсивные шаблоны для построения форма, если я не использую рекурсивные шаблоны, я получаю форму для работы. Однако с рекурсивными шаблонами я получаю ошибки:

<form [formGroup]="myForm">

  <div class="form-group">


    <ng-template #nodeTemplateRef let-node>

      <div class="node">
        <div  *ngIf="node.children.length">
          {{"section [formGroupName]="}} {{ getNodeKey(node) }}
          <section style="display:block;margin:20px;border:solid 1px blue;padding-bottom: 5px;"
            [formGroupName]="getNodeKey(node)" >
            <h1>{{ node.key }}</h1>
            <ng-template
              ngFor
              [ngForOf]="node.children"
              [ngForTemplate]="nodeTemplateRef">
            </ng-template>
          </section>
          {{"end of section"}}
        </div>
        <div  *ngIf="!node.children.length">
          <label [for]="node.key">{{node.key}}</label>&nbsp;
          <input  type="text" [id]="node.key"
                  class="form-control">
        </div>
      </div>

    </ng-template>

    <ng-template *ngFor="let myKey of myKeys"
                 [ngTemplateOutlet]="nodeTemplateRef"
                 [ngTemplateOutletContext]="{ $implicit: myKey   }">
    </ng-template>

  </div>

FormerComponent. html: 25 Ошибка: Ошибка: не удается найти элемент управления с именем: 'road'

That соответствует этому образцу JSON:

"address": {
        "town": "townington",
        "county": "Shireshire",

        "road": {
          "number": "1",
          "street": "the street"
        }

У меня отображается, поэтому я знаю, что элементы там. Чего мне не хватает?

Ответы [ 2 ]

9 голосов
/ 21 января 2020

Проблема с вашим текущим кодом, кажется, в том, что родительский элемент ng-шаблона является компонентом вашего приложения, поэтому он не учитывает другие formGroupNames в верхних шаблонах, которые вы определили, и всегда ищет в root FormGroup.

It Также кажется, что полное имя группы / имя элемента управления не поддерживается в шаблонах (например, нельзя использовать formGroupName="address.road")

Если вам по каким-то причинам нужна формаГруппы - вы можете передать их в контексте шаблонам. Или вы можете обратиться к formControls напрямую:

  • удалить все formGroupName из шаблона
  • store fullPath: keys.push({"key":key,children:[], fullKey: parent ? parent.fullKey + '.' + key: key}); (вы можете хранить FormControl сам экземпляр, а также c .)
  • и используйте его: <input type="text" [formControl]="myForm.get(node.fullKey)"

Пример Stackblitz

2 голосов
/ 25 января 2020

Или, если вам все еще нужна иерархия групп / элементов управления, вы можете использовать директивы formGroup и formControl, передавая их рекурсивно (вместо formGroupName и formControlName)

Ссылка на стек стека

NB: та же проблема здесь: Рекурсивная ReactiveForm не может найти группы форм внутри шаблона

...