2012-12-17 94 views
5

我想用knockout動態地呈現行和列。我的想法是,我想用一些單元格填充每行,並根據需要動態添加更多行。 讓我們假設細胞的totall數等於行的4 *號,然後我想:如何在knockout.js中有條件地呈現tr foreach綁定

<table> 
    <tbody data-bind="foreach: model"> 
     <!--ko if: $index() % 4 == 0--><tr><!--/ko--> 
     <td> 
       <label data-bind="text: Value"></label> 
     </td> 
     <td> 
       <input type="checkbox" data-bind="checked: IsChecked"/> 
     </td> 
     <!--ko if: $index() % 4 == 0--></tr><!--/ko--> 
    </tbody> 
</table> 

,但它的工作原理就像是:通過不使整行的內容

<table> 
    <tbody data-bind="foreach: model"> 
     <!--ko if: $index() % 4 == 0--> 
     <td> 
       <label data-bind="text: Value"></label> 
     </td> 
     <td> 
       <input type="checkbox" data-bind="checked: IsChecked"/> 
     </td> 
     </tr><!--/ko--> 
    </tbody> 
</table> 

,是它可能用敲除渲染所有單元格,並只在需要時添加行?

作爲一種解決方法,我考慮嵌套的foreach,但它需要我的模型從單維更改爲二維,這看起來很奇怪。

+2

您確定要使用的HTML表呢?如果你有一個扁平的物品清單作爲你的數據,你不僅可以將它們渲染爲div並使用CSS讓它們在一個容器內自然流動,而且還可以跨越4個? –

+0

是的,它是表格數據和表格用於顯示錶格數據使用div將是解決方法不是一個解決方案 – 0lukasz0

回答

14

添加另一個計算的屬性,你的數據結構到行:

<table> 
    <tbody data-bind="foreach: rows"> 
     <tr> 
      <!-- ko foreach: $data --> 
      <td data-bind="text:$index"></td> 
      <td data-bind="text:fname"></td> 
      <td data-bind="text:lname"></td> 
      <!-- /ko --> 
     </tr> 
    </tbody> 
</table> 

與代碼:

var vm = { 

    people: ko.observableArray([ 
     { fname: 'fname', lname: 'lname' }, 
     { fname: 'fname', lname: 'lname' }, 
     { fname: 'fname', lname: 'lname' }, 
     { fname: 'fname', lname: 'lname' } 
    ]) 
}; 

vm.rows = ko.computed(function() { 

    var itemsPerRow = 3, rowIndex = 0, rows = []; 

    var people = vm.people(); 
    for (var index = 0; index < people.length; index++) { 
     if (!rows[rowIndex]) 
      rows[rowIndex] = []; 

     rows[rowIndex].push(people[index]); 

     if (rows[rowIndex].length == itemsPerRow) 
      rowIndex++; 
    } 

    return rows; 
}, vm); 

$(function() { 
    ko.applyBindings(vm); 
}); 
+0

超級酷...保存我的一天 – dreamerkumar

+0

正是我在找的,謝謝... – ShaneBlake

3

僅僅因爲它使用DOM,您的語法將無法與knockout默認模板引擎一起使用。 如果你需要這樣做,使用基於字符串的外部模板引擎(它會將你的模板當作字符串處理,並使用正則表達式和字符串操作,這樣你就可以通過有條件的渲染開始/結束標籤來完成這個技巧)。 你的榜樣使用下劃線JS:

http://jsfiddle.net/2QKd3/5/

HTML

<h1>Table breaking</h1> 
<ul data-bind="template: { name: 'peopleList' }"></ul> 

<script type="text/html" id="peopleList"> 
    <table> 
    <tbody> 
    {{ _.each(model(), function(m, idx) { }} 
     {{ if (idx % 4 == 0) { }} 
      <tr> 
     {{ } }} 
     <td> 

       <label>{{= m.Value }}</label> 
     </td> 
     <td> 
      <input type="checkbox" data-bind="checked: m.IsChecked"/> 
     </td> 
     {{ if (idx % 4 == 3) { }} 
     </tr> 
     {{ } }} 
    {{ }) }} 
      </tbody> 
      </table> 
</script> 

的Javascript(這包括強調整合描述下在這裏 - http://knockoutjs.com/documentation/template-binding.html

_.templateSettings = { 
    interpolate: /\{\{\=(.+?)\}\}/g, 
    evaluate: /\{\{(.+?)\}\}/g 
}; 

/* ---- Begin integration of Underscore template engine with Knockout. Could go in a separate file of course. ---- */ 
    ko.underscoreTemplateEngine = function() { } 
    ko.underscoreTemplateEngine.prototype = ko.utils.extend(new ko.templateEngine(), { 
     renderTemplateSource: function (templateSource, bindingContext, options) { 
      // Precompile and cache the templates for efficiency 
      var precompiled = templateSource['data']('precompiled'); 
      if (!precompiled) { 
       precompiled = _.template("{{ with($data) { }} " + templateSource.text() + " {{ } }}"); 
       templateSource['data']('precompiled', precompiled); 
      } 
      // Run the template and parse its output into an array of DOM elements 
      var renderedMarkup = precompiled(bindingContext).replace(/\s+/g, " "); 
      return ko.utils.parseHtmlFragment(renderedMarkup); 
     }, 
     createJavaScriptEvaluatorBlock: function(script) { 
      return "{{ " + script + " }}"; 
     } 
    }); 
    ko.setTemplateEngine(new ko.underscoreTemplateEngine()); 
/* ---- End integration of Underscore template engine with Knockout ---- */ 

var viewModel = { 
    model: ko.observableArray([ 
     { Value: '1', IsChecked: 1 }, 
     { Value: '2', IsChecked: 0 }, 
     { Value: '3', IsChecked: 1 }, 
     { Value: '4', IsChecked: 0 }, 
     { Value: '5', IsChecked: 1 }, 
    ])   
}; 

ko.applyBindings(viewModel); 

P.S:但BETT呃avoid using tables for html layout。您的示例可以使用更簡潔的代碼使用行內塊元素進行渲染。

+0

+1與DOM與文本模板,但我不想使用另一個模板引擎 – 0lukasz0

相關問題