I've been looking at examples of nested foreach
loops in knockout
all afternoon, and I haven't been able to get anything working. My current setup, at least the relevant parts, are below.
ViewModel:
var sample = {
this.pageData = ko.observable();
this.panels = ko.observableArray();
};
ko.utils.extend(sample.prototype, {
activate: {
this.pageData(sampleData);
this.panels([
{
name: 'column1',
keys: ['key1', 'key2', 'key3'],
loadedWidgets: ko.observableArray()
},
{
name: 'column2',
keys: ['key4', 'key5'],
loadedWidgets: ko.observableArray()
},
{
name: 'column3',
keys: ['key6'],
loadedWidgets: ko.observableArray()
}
]);
this.loadWidgetPanels(this.panels(), this.pageData());
},
loadWidgetPanels: function (panels, pageData) {
for (var i = 0; i < panels.length; i++) {
var screens = filterContentByKey(pageData.Content, panels[i].keys);
if (screens) {
panels[i].loadedWidgets.push(widgetFactory.getWidgets(screens));
}
}
}
}
View:
<div>
<!-- ko foreach: panels -->
<div class="3columnStyle">
<!-- ko foreach: loadedWidgets -->
<!--ko compose: $data --><!-- /ko -->
<!-- /ko -->
</div>
<!-- /ko -->
</div>
I've confirmed that I'm getting back the right data in the right format in my loadedWidgets
, but they don't display in the view. I can tell that the view at least knows how much data is there, because my DOM has a ko compose
element for each widget. For example, the first column has a handful of widgets, and that div gets created with a handful of widgets in it. Column 2 has 2 widgets, and it gets 2 compose
elements. Column 3 has 1 widget and gets one element. It's just not displaying the widgets themselves. Do I need additional elements or additional binding somewhere?
I have a working model of this that doesn't rely on nested loops. Instead of using the array of objects, it just creates each of the observable arrays. In other words, it's not looping. Instead of one array containing three objects, each with its own array, I have three arrays:
this.column1Widgets();
this.column2Widgets();
this.column3Widgets();
They're constructed the same way, just manually instead of looping. And the View looks more like this:
<div class="3columnStyle">
<!-- ko foreach: column3Widgets -->
<!-- ko compose: $data --><!-- /ko -->
<!-- /ko -->
</div>
<div class="3columnStyle">
<!-- ko foreach: column3Widgets -->
<!-- ko compose: $data --><!-- /ko -->
<!-- /ko -->
</div>
<div class="3columnStyle">
<!-- ko foreach: column3Widgets -->
<!-- ko compose: $data --><!-- /ko -->
<!-- /ko -->
</div>
I'm not sure why it's not working with the nested loop, but since the data is identical, I'm sure there's something I'm missing in setting up the View.