简体   繁体   中英

KnockoutJS: foreach binding array inside observable

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!

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> 

Here's a fiddle for testing

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM