我想使用knockout动态渲染行和列。我的想法是,我希望用一些单元格填充每一行,并根据需要动态添加更多行。 让我们假设整个单元格数等于4 *行数,然后我尝试了:
<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>
通过不用内容渲染整行,是否可以使用knockout渲染所有单元格并仅在需要时添加行?
作为一种解决方法,我考虑嵌套的foreach,但它需要我的模型从单维变为二维,这似乎很奇怪。
答案 0 :(得分: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);
});
答案 1 :(得分:3)
您的语法不适用于淘汰默认模板引擎,因为它使用DOM。 如果您需要这样做,请使用基于字符串的外部模板引擎(它将您的模板视为字符串,并将使用正则表达式和字符串操作,因此您将能够使用条件呈现开始/结束标记来执行此操作)。 您的示例使用下划线js:
<强> 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。:但更好avoid using tables for html layout。您的示例可以使用带有更清晰代码的内联块元素进行渲染。