Reputation: 4011
This is my data model (a survey):
{
"name" : "x",
"questions" : [ .... ]
}
This is my viewModel:
survey : ko.observable(undefined)
This is my data-bind tag:
<ol data-bind="foreach: data.survey.questions">
It doesn't work. It works if I change the binding like this:
<ol data-bind="foreach: data.survey().questions">
The problem is that inside the foreach binding there's another foreach looping through the possible answers to the questions:
<div data-bind="foreach: answers">
I didn't find any way to make this one work with my current setup. Basically I think the problem is that you need to use an observableArray
but I want to loop on an array inside an observable instead.
Can anyone suggest a way to make this double foreach work? Thanks!
Upvotes: 3
Views: 1704
Reputation: 35202
Knockout observables are functions. To read the observable
’s value, you need to call the observable with no parameters. Hence you need the survey()
to access the inner object which has questions
property.
I'm not sure why your inner foreach
binding isn't working. I would guess it's because you are setting survey
to undefined
. But since the outer foreach
is working it couldn't be that. And you mentioned, "I think the problem is that you need to use an observableArray". That's not necessary. Knockout's default binding handlers, including the foreach
binding, internally handle this by using ko.utils.unwrapObservable()
. The only difference being, if it's an observableArray
, any changes to the array in the future will be reflected on the UI. But if it's a regular array, then the UI won't be updated.
So, if there is an array called answers
within each question
, then it should work. Here's a working snippet.
var data = {
survey: ko.observable({
"name": "x",
"questions": [{
text: "Who let the dogs out?",
answers: [
{number: 1,text: "Cats"},
{number: 2,text: "Baha Men"}
]
}, {
text: "What does the fox say?",
answers: [
{number: 1,text: "Woof Woof"},
{number: 2,text: "Ring-ding-ding-dingeringeding"},
{number: 3,text: "Meow Meow"}
]
}]
})
};
ko.applyBindings(data)
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.1/knockout-min.js"></script>
<ol data-bind="foreach: survey().questions">
<li>
<span data-bind="text: text"></span>
<br> Answers:
<ul data-bind="foreach: answers">
<li data-bind="text:text">
</li>
</ul>
</li>
</ol>
Upvotes: 1