2014-01-24 26 views
2

鑑於嵌套類的這種模型和視圖模型遞歸使用模板:如何knockout.js

function Category(id, name) { 
    var self = this; 
    self.Id = ko.observable(id || '00000000-0000-0000-0000-000000000000'); 
    self.Name = ko.observable(name); 
    self.children = ko.observableArray(); 

    self.addCategory = function() { 
     self.children.push(new Category("", "")); 
    }; 

    self.removeCategory = function(category) { 
     self.children.remove(category); 
    }; 
} 

var CategoryManagerViewModel = function() { 
    var self = this; 
    self.children = ko.observableArray(); 

    self.addCategory = function() { 
     self.children.push(new Category("", "")); 
    }; 

    self.removeCategory = function (category) { 
     self.children.remove(category); 
    }; 

    self.save = function() { 
     self.lastSavedJson(JSON.stringify(ko.toJS(self.children), null, 2)); 
    }; 

    self.lastSavedJson = ko.observable(""); 
}; 

如何使模板等,隨着越來越多的孩子類別嵌套(再嵌套在這些類別類別等)模板繼續被重用來反映這一點?

此刻我的模板是:

<table class='categoriesEditor'> 
       <tr> 
        <th>Category</th> 
        <th>Children</th> 
       </tr> 
       <tbody data-bind="foreach: children"> 
        <tr> 
         <td> 
          <input data-bind='value: Name' /> 

          <div><a href='#' style="color:black" data-bind='click: removeCategory'>Delete</a></div> 
         </td> 
         <td> 
          <table> 
           <tbody data-bind="foreach: children"> 
            <tr> 
             <td><input data-bind='value: Name' /></td> 
             <td><a href='#' style="color:black" data-bind='click: removeCategory'>Delete</a></td> 
             <td> 
              <table> 
               <tbody data-bind="foreach: children"> 
                <tr> 
                 <td><input data-bind='value: Name' /></td> 
                 <td><a href='#' style="color:black" data-bind='click: removeCategory'>Delete</a></td> 
                </tr> 
               </tbody> 
              </table> 
              <a href='#' style="color:black" data-bind='click: addCategory'>Add cat</a> 
             </td> 
            </tr> 
           </tbody> 
          </table> 
          <a href='#' style="color:black" data-bind='click: addCategory'>Add cat</a> 
         </td> 
        </tr> 
       </tbody> 
      </table> 
     </div> 

     <p> 
      <button data-bind='click: addCategory'>Add root category</button> 
      <button data-bind='click: save, enable: children().length > 0'>Save to JSON</button> 
     </p> 

這讓我3個級別分類中嵌套,這是/將被罰款這一應用程序,但如果我想要更多嗎?我是否爲此複製了粘貼標記?當然不是,我會認爲我已經完成了。

更新:

綁定如下:

var viewModel = new CategoryManagerViewModel(); 
     viewModel.addCategory(); 
     ko.applyBindings(viewModel); 
+0

對投票?爲什麼?? – rism

+0

別擔心,完美的問題。我想象變幻無常的原因是你的代碼格式不正確。 – Jamiec

回答

5

對於這樣的情況,你可能需要使用一個命名模板,你可以遞歸調用。所以,你將有一個設置(簡體),如:

<table> 
    <tbody data-bind="template: { name: 'itemTmpl', data: root }"></tbody> 
</table> 

<script id="itemTmpl" type="text/html"> 
     <tr> 
      <td data-bind="text: name"></td> 
      <td> 
       <table> 
        <tbody data-bind="template: { name: 'itemTmpl', foreach: children }"></tbody> 
       </table> 
      </td> 
     </tr> 
</script> 

所以,你可以調用一個根音的模板,然後從那裏調用它的孩子(這將調用它自己的孩子,等等。 )

這裏的樣本:http://jsfiddle.net/rniemeyer/ex3xt/

+0

好東西,謝謝。也許是一個不同的問題,但是當我動態改變孩子時,這應該會自動更新嗎?它不在莫,但也許我做了不正確的事情或不支持。 – rism

+0

別擔心 - 我解決了。在您的jsFiddle中,您使用visible:children.length作爲是否顯示子模板的條件測試。完美無瑕,因爲你使用普通的舊數組作爲兒童的類型。不過,我正在使用 self.children = ko.observableArray(); 這需要一個函數調用來讀取值,使您的小提琴工作我需要將「visible:children.length」更改爲「visible:children()。length」。再次感謝。 – rism