動的再帰テンプレートを備えたReactiveForms


8

これが私の問題です。

問題のオンライン例

フォームに変換する必要がある動的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」のコントロールが見つかりません

これは、次のサンプルJSONに対応しています。

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

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

表示されているので、要素が存在することがわかります。何が欠けていますか?


私は[formGroupName]="road"それがaddressフォームグループの下にネストされていることを認識していません。roadルートの直下にある名前のフォームグループを探してい[formGroup]="myForm"ます。のroad直下にフォームグループをネストするとmyForm、エラーが表示されなくなります。
Alex K

交換formGroupNameformGroupどこでもして問題を解決することがあります。ただしFormGroup、ネストされたグループごとに正しいインスタンスを取得する方法が必要です。
アレックスK

それはこの他のエラーを作成します>文字列 'name'でプロパティ 'validator'を作成できません
Dalorzo

動的jsonは常に既知のセットを返しますか?それは変わる可能性がありますが、私たちはそれらを認識し、タイプセーフなものを持っていますか?
maxime1992

私は私が求めていることだと思います。それは本当にダイナミックであるか、それだけであるoneOfように可能なエントリの既知のセットからnamepersonaladdressなど
maxime1992

回答:


2

または、フォームグループ/コントロール階層が必要な場合は、formGroupおよびformControlディレクティブを再帰的に渡すことで(formGroupNameおよびformControlNameの代わりに)使用できます。

Stackblitsリンク

注意:同じ問題がここにあります:再帰的なReactiveFormがテンプレート内でformGroupsを見つけることができません


1
この+1は1つの印象的な解決策..です
Dalorzo

これは最終的にはうまく機能するようになり、元の目標に必要な変更が少なくなりました。私はそれがより正確だと思うので、私がそれに応答を与える理由です
Dalorzo

9

現在のコードの問題は、ng-templateの親がアプリコンポーネントであるため、定義したトップテンプレートの他のformGroupNamesを考慮せず、常にルートFormGroupでシークします。

また、完全なグループ名/コントロール名はテンプレートではサポートされていないようです(たとえば、は使用できませんformGroupName="address.road")。

何らかの理由でformGroupsが必要な場合は、それらをコンテキストでテンプレートに渡すことができます。または、直接formControlsをアドレス指定できます。

  • formGroupNameテンプレートからすべて削除
  • fullPath keys.push({"key":key,children:[], fullKey: parent ? parent.fullKey + '.' + key: key});を保存しFormControlます(インスタンス自体も保存できます)。
  • そしてそれを使う: <input type="text" [formControl]="myForm.get(node.fullKey)"

Stackblitzの例

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.