knockout unable to process binding “foreach”

断了今生、忘了曾经 提交于 2019-12-03 13:06:29

When you do this (in fetchYear):

ko.applyBindings(new YearViewModel(yearData));

You are binding the entire page with the YearViewModel view model. But the YearViewModel doesn't have a property called ageView so you get the error and knockout stops trying to bind anything else.

What you need to do is restrict your bindings to cover only part of the dom by passing the element you want to ko.applyBindings. For example:

<div class="row" id="yearVM" data-bind="foreach: yearView">
//....
<div class="row" id="popVM" data-bind="foreach: ageView">

And then:

ko.applyBindings(new YearViewModel(yearData), document.getElementById("yearVM"));
//...
ko.applyBindings(new PopulationViewModel(populationData), document.getElementById("popVM"));

Now your bindings are restricted just to the part of the DOM that actually displays stuff from that model.

Another alternative is to just have your two view models as part of a parent view model and then you can apply the binding to the entire page. This makes it easier if you need to mix parts from both VMs and they are not conveniently separated in distinct sections of your page. Something like:

var myParentVM = {
    yearVM : index.fetchYear(),          // note, make this return the VM instead of binding it
    popVM : index.fetchPopulation(),     // ditto
}

ko.applyBindings(myParentVM);

And then you'd declare your bindings like so:

<div class="row" data-bind="foreach: yearVM.yearView">

The main reason why this is not working is because you call ko.applyBindings() more than once on a page (that is not really forbidden but is a bad practice in my opinion).

If you need to call it twice, you must call it with a container for which region this bind is meant to.

Something like this:

ko.applyBindings(new YearViewModel(yearData), document.getElementById('YourYearViewElementId'));

The error you get is from the first binding, which tries to process the whole page and does not find the 'ageView' in its ViewModel.

Better would be if you build a single ViewModel for a single Page where you have sub-models for sections if needed.

Some pseudo code for such a scenario:

var Section1ViewModel = function() {
    var self = this;

    self.property1 = ko.observable();
    self.myComputed = ko.computed(function () {
        // do some fancy stuff
    });
    self.myFunc = function() {
        // do some more fancy stuff
    };
}

var Section2ViewModel = function() {
    var self = this;

    self.property1 = ko.observable();
    self.myComputed = ko.computed(function () {
        // do some fancy stuff
    });
    self.myFunc = function() {
        // do some more fancy stuff
    };
}

var PageViewModel = function() {
    var self = this;

    self.section1 = ko.observable(new Section1ViewModel());
    self.section2 = ko.observable(new Section2ViewModel());

    self.myGlobalFunc = function() {
        // do some even more fancy stuff
    }
}

ko.applyBindings(new PageViewModel());

Hope that helps.

Best regards, Chris

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!