Reputation: 9599
I have an array of items, and I want to group them into multiple sections based on the data within that array. I'm using KO if conditionals successfully, but I have to repeat the section markup and conditional for each section I want. I want to convert the section to a template to avoid repetition, but I don't know how to include the if condition in the template using a variable rank. Is there a way to pass a variable to a template and reference that variable within the template?
Here is the HTML:
<strong>Rank 1:</strong><br/>
<ul data-rank="1" data-bind="foreach: listItems">
<!-- ko if: rank == 1 -->
<li data-bind="text: name + ' (' + rank + ')'"></li>
<!-- /ko -->
</ul>
<strong>Rank 2:</strong><br/>
<ul data-rank="2" data-bind="foreach: listItems">
<!-- ko if: rank == 2 -->
<li data-bind="text: name + ' (' + rank + ')'"></li>
<!-- /ko -->
</ul>
<strong>Rank 3:</strong><br/>
<ul data-rank="3" data-bind="foreach: listItems">
<!-- ko if: rank == 3 -->
<li data-bind="text: name + ' (' + rank + ')'"></li>
<!-- /ko -->
</ul>
And the JavaScript:
$(document).ready(function() {
var viewModel = {};
viewModel.listItems = ko.observableArray();
viewModel.listItems.push({name: "A", rank: 1});
viewModel.listItems.push({name: "B", rank: 1});
viewModel.listItems.push({name: "C", rank: 2});
viewModel.listItems.push({name: "D", rank: 2});
viewModel.listItems.push({name: "E", rank: 1});
viewModel.listItems.push({name: "F", rank: 3});
viewModel.listItems.push({name: "G", rank: 2});
ko.applyBindings(viewModel);
});
And a working fiddle:
http://jsfiddle.net/RationalGeek/9eftr/
Upvotes: 1
Views: 363
Reputation: 139788
I would create a filter function on the viewmodel:
viewModel.filterByRank = function(rank) {
return ko.utils.arrayFilter(viewModel.listItems(), function(item) {
return item.rank == rank;
});
}
And then use this function in the bindings:
<strong>Rank 1:</strong><br/>
<ul data-rank="1"
data-bind="template: { name: 'temp', foreach: filterByRank(1) }">
</ul>
<strong>Rank 2:</strong><br/>
<ul data-rank="2"
data-bind="template: { name: 'temp', foreach: filterByRank(2) }">
</ul>
<strong>Rank 3:</strong><br/>
<ul data-rank="3"
data-bind="template: { name: 'temp', foreach: filterByRank(3) }">
</ul>
<script id="temp" type="text/html">
<li data-bind="text: name + ' (' + rank + ')'"></li>
</script>
Demo JSFiddle.
Or you can move your whole markup to a template and use it like:
<!-- ko template: { name: 'temp', data: { rank: 1, items: filterByRank(1) } } -->
<!-- /ko -->
<script id="temp" type="text/html">
<strong>Rank <!-- ko: text: rank --><!-- /ko --></strong>
<br/>
<ul data-bind="foreach: items, attr: { 'data-rank': rank}">
<li data-bind="text: name + ' (' + rank + ')'"></li>
</ul>
</script>
Demo JSFiddle.
Upvotes: 1