71

フォーム要素のネストされたグループを含むJSONオブジェクトから動的にフォームを構築しようとしています。

  $scope.formData = [
  {label:'First Name', type:'text', required:'true'},
  {label:'Last Name', type:'text', required:'true'},
  {label:'Coffee Preference', type:'dropdown', options: ["HiTest", "Dunkin", "Decaf"]},
  {label: 'Address', type:'group', "Fields":[
      {label:'Street1', type:'text', required:'true'},
      {label:'Street2', type:'text', required:'true'},
      {label:'State', type:'dropdown',  options: ["California", "New York", "Florida"]}
    ]},
  ];

私はng-switchブロックを使用してきましたが、上記のAddressオブジェクトのように、ネストされたアイテムでは使用できなくなります。

これがフィドルです:http: //jsfiddle.net/hairgamiMaster/dZ4Rg/

このネストされた問題に最適にアプローチする方法についてのアイデアはありますか?どうもありがとう!

4

5 に答える 5

123

これはあなたを助けることができると思います。これは、ツリー内の再帰要素についてGoogleグループで見つけた回答からのものです。

提案はブレンダンオーウェンからです:http://jsfiddle.net/brendanowen/uXbn6/8/

<script type="text/ng-template" id="field_renderer.html">
    {{data.label}}
    <ul>
        <li ng-repeat="field in data.fields" ng-include="'field_renderer.html'"></li>
    </ul>
</script>

<ul ng-controller="NestedFormCtrl">
    <li ng-repeat="field in formData" ng-include="'field_renderer.html'"></li>
</ul>

提案された解決策は、現在の要素に子がある場合にng-includeディレクティブを使用して自分自身を呼び出すテンプレートを使用することです。

あなたの場合、私はng-switchディレクティブを使用してテンプレートを作成し(あなたが行ったようにラベルのタイプごとに1つのケース)、子ラベルがある場合は最後にng-includeを追加しようとします。

于 2013-03-27T15:59:11.377 に答える
10

@jpmorinと@Ketanが提案したことを組み合わせる(実際にはそのままでは機能しないため、@ jpmorinの回答に若干の変更があります)... ng-if「リーフの子」が不要なng-repeatディレクティブを生成しないようにするための方法があります。

<script type="text/ng-template" id="field_renderer.html">
  {{field.label}}
  <ul ng-if="field.Fields">
      <li ng-repeat="field in field.Fields" 
         ng-include="'field_renderer.html'">
      </li>
  </ul>
</script>
<ul>
  <li ng-repeat="field in formData" ng-include="'field_renderer.html'"></li>
</ul>

これがPlunkerの作業バージョンです

于 2014-05-11T18:23:15.340 に答える
1

Fieldsプロパティの可用性を確認するためにng-switchの使用を検討する場合があります。その場合は、その条件に別のテンプレートを使用します。このテンプレートには、Fields配列にng-repeatがあります。

于 2013-03-27T14:43:46.650 に答える
1

私はこれが古い質問であることを知っています、しかし検索を通してここに来るかもしれない他の人のために、私は私にもう少しきちんとした解決策を残したいと思います。

同じアイデアに基づいていますが、テンプレートをテンプレートキャッシュなどに保存する必要はありません。より「クリーンな」ソリューションが必要だったため、https://github.com/dotJEM/angular-treeを作成することになりました。

使い方はかなり簡単です。

<ul dx-start-with="rootNode">
  <li ng-repeat="node in $dxPrior.nodes">
    {{ node.name }}
    <ul dx-connect="node"/>
  </li>
</ul>

ディレクティブはコンパイルの代わりにトランスクルージョンを使用するため(最新バージョンの場合)、これはng-includeの例よりもパフォーマンスが優れているはずです。

ここのデータに基づく例:

angular
  .module('demo', ['dotjem.angular.tree'])
  .controller('AppController', function($window) {

    this.formData = [
      { label: 'First Name', type: 'text', required: 'true' },
      { label: 'Last Name',  type: 'text', required: 'true' }, 
      { label: 'Coffee Preference', type: 'dropdown', options: ["HiTest", "Dunkin", "Decaf"] }, 
      { label: 'Address', type: 'group',
      "Fields": [{
        label: 'Street1', type: 'text', required: 'true' }, {
        label: 'Street2', type: 'text', required: 'true' }, {
        label: 'State',   type: 'dropdown', options: ["California", "New York", "Florida"]
      }]
    }, ];

    this.addNode = function(parent) {
      var name = $window.prompt("Node name: ", "node name here");
      parent.children = parent.children || [];
      parent.children.push({
        name: name
      });
    }

    this.removeNode = function(parent, child) {
      var index = parent.children.indexOf(child);
      if (index > -1) {
        parent.children.splice(index, 1);
      }
    }

  });
<div ng-app="demo" ng-controller="AppController as app">

   <form>
        <ul class="unstyled" dx-start-with="app.formData" >
            <li ng-repeat="field in $dxPrior" data-ng-switch on="field.type">
                <div data-ng-switch-when="text">
                    <label>{{field.label}}</label>
                    <input type="text"/>
                </div>
                <div data-ng-switch-when="dropdown">
                    <label>{{field.label}}</label>
                    <select>
                        <option ng-repeat="option in field.options" value="{{option}}">{{option}}</option>
                    </select>
                </div>
                <div data-ng-switch-when="group" class="well">
                    <h2>{{field.label}}</h2>
                    <ul class="unstyled" dx-connect="field.Fields" />
                </div>   
            </li>
        </ul>
            <input class="btn-primary" type="submit" value="Submit"/>
    </form>
  
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>
  <script src="https://rawgit.com/dotJEM/angular-tree-bower/master/dotjem-angular-tree.min.js"></script>

</div>

于 2014-06-22T09:52:12.933 に答える
0

プロパティベースの構造の場合は、jpmorinpostを拡張したいだけです。

JSON

{
  "id": 203,
  "question_text_id": 1,
  "yes": {
    "question_text_id": 25,
    "yes": {
      "question_text_id": 26
    }
  },
  "no": {
    "question_text_id": 4
  }
}

ご覧のとおり、ここのjsonオブジェクトには配列構造が含まれていません。

HTML

<div>
    <script type="text/ng-template" id="tree_item_renderer.html">
        <span>{{key}} {{value}}</span>
        <ul>
            <li ng-repeat="(key,value) in value.yes" ng-include="'tree_item_renderer.html'"></li>
            <li ng-repeat="(key,value) in value.no" ng-include="'tree_item_renderer.html'"></li>
        </ul>
    </script>

    <ul>
        <li ng-repeat="(key,value) in symptomeItems" ng-include="'tree_item_renderer.html'"></li>
    </ul>
</div>

この場合、それを繰り返すことができます。

ng-repeat overプロパティのAngularドキュメントはこちら

いくつかの行の実装はここにあります。

于 2014-09-03T09:27:41.953 に答える