nested foreach
https://groups.google.com/d/topic/knockoutjs/J_PgZU2L5Nk/discussion
by gene
HTML
<script src="http://rniemeyer.github.com/KnockMeOut/Scripts/jquery.tmpl.js"></script>
<script src="https://github.com/SteveSanderson/knockout/raw/master/build/output/knockout-latest.debug.js"></script>
<div>Searcher: <span data-bind="text: searcher().name"></span></div>
<div>Topic: <span data-bind="text: activeTopic().title"> </span></div>
<div>Topics: <span data-bind="text: topics().length"> </span></div>
<hr />
<div class="topicMenu" data-bind='template: { name: "topicMenuTemplate", foreach: topics }'> </div>
<script type="text/html" id="topicMenuTemplate">
<a href="#" data-bind="click: select, css: {active: selected()}"><span class="menuitem" data-bind="text: title()"> </span></a>
</script>
<hr />
<div class="topicDetail" data-bind='template: { name: "topicTemplate", data: activeTopic}'> </div>
<script type="text/html" id="topicTemplate">
<div>
<span data-bind="text: queries().length"> </span> queries:
<div class="queries">
<div data-bind='template: {name: "queryTemplate", foreach: queries}'></div>
</div>
</div>
</script>
<script type="text/html" id ="queryTemplate">
<div class="query" data-bind="css: { active: selected()}">
<span data-bind="click: select">{{= text}}</span>
<span>by</span> <span data-bind='template: {name: "personTemplate", data: searcher }'> </span>
</div>
</script>
<script type="text/html" id ="personTemplate">
<span class="person" data-bind="style: { color: color() }">{{= name()}}</span>
</script>
CSS
body {
font-family: sans-serif;
font-color: black;
}
a {
text-decoration: none;
}
span.menuitem {
display: inline-block;
margin: 10px;
font-weight: bold;
}
.active {
background: lightgrey;
}
JavaScript
var topic = function(id, title, queries, viewModel) {
this.id = ko.observable(id);
this.title = ko.observable(title);
this.queries = ko.observableArray(queries);
this.currentQuery = ko.observable();
this.viewModel = viewModel;
this.selected = function() {
return this.viewModel.activeTopic() == this;
};
this.select = function() {
this.viewModel.activeTopic(this);
}
this.toString = function() { return "[" + this.id() + "] topic"; };
return this;
};
var query = function(id, text, searcher ) {
this.id = ko.observable(id);
this.text = ko.observable(text);
this.topic = topic;
this.searcher = ko.observable(searcher);
this.selected = function() {
return this.topic.currentQuery() == this;
};
this.select = function() {
this.topic.currentQuery(this);
};
return this;
};
var searcher = function(id, name, color) {
this.id = ko.observable(id);
this.name = ko.observable(name);
this.color = ko.observable(color);
return this;
};
var people = [new searcher(1, 'Joe Searcher', 'red'), new searcher(2, 'Library Loon', 'blue')];
var viewModel = {
searcher: ko.observable(people[0]),
topics: ko.observableArray([]),
activeTopic: ko.observable()
};
var queries = [new query(1, 'first query', people[0]), new query(2, 'second query', people[1]),
new query(3, 'third query', people[0]),
new query(4, 'fourth query', people[1]), new query(5, 'fifth query', people[1]),
new query(6, 'last query', people[1])];
var topics = [
new topic(1, 'first', [queries[0], queries[1], queries[2]], viewModel),
new topic(2, 'second topic', [queries[3], queries[4]], viewModel)
];
queries[0].topic = topics[0];
queries[1].topic = topics[0];
queries[2].topic = topics[0];
queries[3].topic = topics[1];
queries[4].topic =...