2013-03-27 29 views
70

我試圖從一個JSON對象,其中包含表單元素的嵌套組動態構建的一種形式:如何在使用嵌套對象時在AngularJS中製作遞歸模板?

$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"]} 
    ]}, 
    ]; 

我一直在使用納克開關塊被,但它變得站不住腳嵌套項目,如在上面的地址對象中。

這裏的小提琴: http://jsfiddle.net/hairgamiMaster/dZ4Rg/

如何最好地處理這個問題,嵌套的任何想法?非常感謝!

+0

我只是在一個非常通用的方式回答了這個在上一個不同的問題角文檔:http://stackoverflow.com/questions/ 14430655 /遞歸角度指令/ 29736154#29736154 – tilgovi 2015-04-19 22:02:41

回答

117

我認爲這可以幫助你。它來自我在Google Group上找到的關於樹中遞歸元素的答案。

的建議是由布倫丹·歐文: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指令的模板(每個標籤類型一個例子,就像你做的那樣),並且如果有任何子標籤,則在最後添加ng-include。

+2

非常感謝 - 我認爲這是使用的技巧。乾杯! – 2013-03-30 17:29:44

+0

如果你的數據結構不重複,那麼你不能使用中繼器,但是你有不確定數量的嵌套值?請參閱:http://stackoverflow.com/questions/25044253/how-can-you-navigate-a-tree-in-reverse-order-with-angularjs – Randyaa 2014-07-30 20:59:30

+0

見我的回答你的問題:http://stackoverflow.com/a/25047327/1036025 – jpmorin 2014-07-30 21:30:51

1

可能會考慮使用ng-switch來檢查Fields屬性的可用性。如果是這樣,那麼針對該情況使用不同的模板。這個模板在Fields數組上會有一個ng-repeat。

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

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> 

由於指令使用transclusion而不是編譯(如最新版本),這應該表現比NG-包括例如更好。基於

例的數據在這裏:

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>

0

只是想在基於產權結構的情況下,延長jpmorin後:

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-重複過性here

而一些行執行here

相關問題