TvdH
TvdH

Reputation: 1218

Dynamically generate drop-down lists and bind options with knockout.js

This fiddle demonstrates my issue: http://jsfiddle.net/timvdh/QMM5b/2/

One drop-down list will be create with the model, if "Add List" is clicked another one will be created OK, more clicks will produce unbound lists.

This is because the additional observables were created after the model was bound, so they are useless.

// this will create an observable which is not bound to the UI
if (!ko.isObservable(self.listData()[field]))
    self.listData()[field] = ko.observableArray([]);

I guess such scenario isn't that uncommon. What I could do is pre-prepare a big enough list of empty observables (for the self.listData and the self.data properties). My real big fat one page app requires an unknown number of controls (metaData loaded via JSON), so I was hoping there is a better approach.

Upvotes: 2

Views: 1204

Answers (1)

nemesv
nemesv

Reputation: 139748

Only the execution order is wrong in your code:

  • First you need to create the new observable fields on the self.listData()
  • and after that you need to add the field to the self.metaData.push(field); because that will trigger the foreach and by that time your observables will be already.

So your addMetaData should look like this:

self.addMetaData = function() {
    var field = "field" + self.fieldNum++;

    if (!ko.isObservable(self.listData()[field]))
        self.listData()[field] = ko.observableArray([]);

    if (!ko.isObservable(self.data()[field]))
        self.data()[field] = ko.observable("B");           

    self.listData()[field].push(new ListEntry("Value A", "A"));
    self.listData()[field].push(new ListEntry("Value B", "B"));

    self.metaData.push(field);
}

Demo JSFiddle.

Upvotes: 2

Related Questions