ReactiveForms mit dynamischen rekursiven Vorlagen

8

Hier ist mein Problem.

Online Beispiel des Problems

Ich habe einen dynamischen JSON, den ich in ein Formular konvertieren muss. Also habe ich reaktive Formulare verwendet und durch Durchlaufen aller Eigenschaften von JSON entweder eine FormGroup oder FormControl auf folgende Weise erstellt:

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);
  }

Danach verwende ich rekursive Vorlagen, um das Formular zu erstellen. Wenn ich keine rekursiven Vorlagen verwende, funktioniert das Formular. Bei rekursiven Vorlagen werden jedoch Fehler angezeigt:

<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 FEHLER Fehler: Kontrolle mit Name: 'Straße' kann nicht gefunden werden.

Das entspricht diesem Beispiel JSON:

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

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

Ich habe angezeigt, also weiß ich, dass die Elemente da sind. Was vermisse ich?

Dalorzo
quelle
Ich glaube, es [formGroupName]="road"ist nicht bekannt, dass es unter der addressFormulargruppe verschachtelt ist . Es wird nach einer Formulargruppe gesucht, die roaddirekt unter der Wurzel benannt ist [formGroup]="myForm". Wenn Sie eine roadFormulargruppe direkt darunter verschachteln myForm, wird der Fehler nicht mehr angezeigt.
Alex K
Das Ersetzen formGroupNamedurch formGroupüberall kann das Problem beheben. Sie benötigen jedoch eine Möglichkeit, die richtige FormGroupInstanz für jede verschachtelte Gruppe zu ermitteln.
Alex K
das erzeugt diesen anderen Fehler> Eigenschaft 'Validator' kann nicht für Zeichenfolge 'Name' erstellt werden
Dalorzo
Wird der dynamische JSON immer einen bekannten Satz zurückgeben? das könnte sich ändern, aber wir können uns ihrer bewusst sein und etwas sicheres haben?
maxime1992
Ich denke , was ich frage: Ist es wirklich dynamisch oder ist es eine nur oneOfvon einem bekannten Satz von möglichen Einträgen wie name, personal, addressusw.
maxime1992

Antworten:

2

Wenn Sie weiterhin eine Hierarchie von Formulargruppen / Steuerelementen wünschen, können Sie die Direktiven formGroup und formControl verwenden, indem Sie sie rekursiv übergeben (anstelle von formGroupName und formControlName).

Stackblits Link

NB: Gleiches Problem hier: Recursive ReactiveForm kann formGroups nicht in der Vorlage finden

Neji Sghair
quelle
1
Diese +1 ist eine beeindruckende Lösung.
Dalorzo
Dieser funktionierte viel besser und erforderte weniger Änderungen an meinem ursprünglichen Ziel. Deshalb
gebe
9

Das Problem mit Ihrem aktuellen Code scheint zu sein, dass ng-template parent Ihre App-Komponente ist, sodass andere formGroupNames in den von Ihnen definierten Top-Vorlagen nicht berücksichtigt werden und immer in root FormGroup gesucht werden.

Es scheint auch, dass der vollständige Gruppenname / Kontrollname in Vorlagen nicht unterstützt wird (z. B. kann nicht verwendet werden formGroupName="address.road").

Wenn Sie aus irgendeinem Grund formGroups benötigen, können Sie diese im Kontext an Vorlagen übergeben. Oder Sie können formControls direkt ansprechen:

  • Entfernen Sie alle formGroupNameaus der Vorlage
  • store fullPath: keys.push({"key":key,children:[], fullKey: parent ? parent.fullKey + '.' + key: key});(Sie können die FormControlInstanz auch selbst speichern.)
  • und benutze es: <input type="text" [formControl]="myForm.get(node.fullKey)"

Stackblitz Beispiel

Petr Averyanov
quelle