淘汰赛无法处理绑定" foreach"

时间:2014-04-15 13:38:53

标签: javascript jquery knockout.js knockout-2.0

我是Knockout的新手,我正在构建一个实际上是大型计算器的应用程序。到目前为止,我在一个页面上运行了两个淘汰赛实例。一个例子工作得非常好,但是另一个例子完全被打破了,而且似乎根本没有注册?

下面是我的Javascript,fetchYear是完美无缺的功能,fetchPopulation是完全破坏的功能。它似乎没有注册" ageview"从HTML开始,我无法弄清楚。

错误:

  

未捕获的ReferenceError:无法处理绑定" foreach:function   (){return ageView}"消息:未定义ageView

提前致谢。

JS:

var index = {

    fetchYear: function () {
        Item = function(year){
            var self = this;
            self.year = ko.observable(year || '');
            self.chosenYear = ko.observable('');
            self.horizon = ko.computed(function(){
                if(self.chosenYear() == '' || self.chosenYear().horizon == undefined)
                    return [];
                return self.chosenYear().horizon;
            });
        };
        YearViewModel = function(yeardata) {
            var self = this;
            self.yearSelect = yeardata;
            self.yearView = ko.observableArray([ new Item() ]);
            self.add = function(){
                self.yearView.push(new Item("New"));
            }; 
        };
        ko.applyBindings(new YearViewModel(yearData));
    },

    fetchPopulation: function () {
        popItem = function(age){
            var self = this;
            self.age = ko.observable(age || '');
            self.chosenAge = ko.observable('');
            self.population = ko.computed(function(){
                if(self.chosenAge() == '' || self.chosenAge().population == undefined)
                    return [];
                return self.chosenAge().population;
            });
        };
        PopulationViewModel = function(populationdata) {
            var self = this;
            self.ageSelect = populationdata;
            self.ageView = ko.observableArray([ new popItem() ]);
            self.add = function(){
                self.ageView.push(new popItem("New"));
            }; 
        };
        ko.applyBindings(new PopulationViewModel(populationData));
    }

}

index.fetchYear();
index.fetchPopulation();

HTML:

<div class="row" data-bind="foreach: yearView">
    <div class="grid_6">
        <img src="assets/img/index/calendar.png" width="120" height="120" />
        <select class="s-year input-setting" data-bind="options: $parent.yearSelect, optionsText: 'year', value: chosenYear"></select>
        <label for="s-year">Start year for the model analysis</label>
    </div>
    <div class="grid_6">
        <img src="assets/img/index/clock.png" width="120" height="120" />
        <select class="s-horizon input-setting" data-bind="options: horizon, value: horizon"></select>
        <label for="s-horizon">Analysis time horizon</label>
    </div>
</div>

<div class="row" data-bind="foreach: ageView">
    <div class="grid_6">
        <img src="assets/img/index/calendar.png" width="120" height="120" />
        <select class="s-year input-setting" data-bind="options: ageSelect, optionsText: 'age', value: chosenAge"></select>
        <label for="s-agegroup">Age group of <br> target population</label>
    </div>
    <div class="grid_6">
        <img src="assets/img/index/clock.png" width="120" height="120" />
        <input class="s-population input-setting"></input>
        <label for="s-population">Size of your patient <br> population <strong>National</strong> </label>
    </div>
</div>

2 个答案:

答案 0 :(得分:17)

执行此操作时(在fetchYear中):

ko.applyBindings(new YearViewModel(yearData));

您使用YearViewModel视图模型绑定整个页面。但是YearViewModel没有名为ageView的属性,所以你得到错误并且淘汰停止尝试绑定任何其他内容。

您需要做的是通过将您想要的元素传递给ko.applyBindings来限制绑定仅覆盖部分dom。例如:

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

然后:

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

现在,您的绑定仅限于实际显示该模型中的内容的DOM部分。

另一种方法是让您的两个视图模型作为父视图模型的一部分,然后您可以将绑定应用于整个页面。如果您需要混合来自两个VM的部件,并且在页面的不同部分中不方便地将它们分开,这将使其更容易。类似的东西:

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

ko.applyBindings(myParentVM);

然后你就像这样声明你的绑定:

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

答案 1 :(得分:2)

这不起作用的主要原因是因为你在一个页面上多次调用ko.applyBindings()(这不是真的被禁止但在我看来是不好的做法)。

如果你需要调用它两次,你必须用一个容器来调用它,这个容器应该绑定到哪个区域。

这样的事情:

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

你得到的错误来自第一个绑定,它试图处理整个页面而没有找到&#39; ageView&#39;在其ViewModel中。

如果您为单个页面构建单个ViewModel,那么如果需要,您可以使用子模型。

这种情况的一些伪代码:

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());

希望有所帮助。

祝你好运, 克里斯