私はKnockoutを初めて使用し、効果的に大規模な計算機となるアプリを作成しています。これまでのところ、1つのページで2つのノックアウトインスタンスが実行されています。 1つのインスタンスは完全に正常に機能していますが、もう1つのインスタンスは完全に壊れており、まったく登録されていないように見えますか?
以下は私のJavascriptです。fetchYearは完全に正常に機能する関数であり、fetchPopulationは完全に壊れている関数です。 HTMLから「ageview」を登録していないようで、わかりません。
エラー:
Uncaught 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>
これを行うと(fetchYear
で):
ko.applyBindings(new YearViewModel(yearData));
ページ全体をYearViewModel
ビューモデルでバインドしています。ただし、YearViewModel
にはageView
というプロパティがないため、エラーが発生し、ノックアウトは他のものをバインドしようとしなくなります。
あなたがする必要があるのは、あなたが望む要素を渡すことによって、domの一部だけをカバーするようにバインディングを制限することですko.applyBindings
。例えば:
<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の部分だけに制限されます。
もう1つの方法は、2つのビューモデルを親ビューモデルの一部として持つだけで、ページ全体にバインディングを適用できます。これにより、両方の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ページでko.applyBindings()を複数回呼び出すためです(これは実際には禁止されていませんが、私の意見では悪い習慣です)。
2回呼び出す必要がある場合は、このバインドの対象となるリージョンのコンテナーを使用して呼び出す必要があります。
このようなもの:
ko.applyBindings(new YearViewModel(yearData), document.getElementById('YourYearViewElementId'));
発生するエラーは、ページ全体を処理しようとし、ViewModelで「ageView」が見つからない最初のバインディングからのものです。
必要に応じてセクションのサブモデルがある単一のページに対して単一の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());
お役に立てば幸いです。
よろしく、クリス