Reputation: 8568
I am using RPNiemeyer kendo-knockout library. I have three view models that instantiate each other - FranchiseDetailsViewModel
instantiates LanguageListViewModel
which instantiates LanguageDetailsViewModel
. The last viewmodel LanguageDetailsViewModel
needs to have a reference to the parent FranchiseDetailsViewModel
as its functionality depends on it.
html:
<div data-viewId="languageList" >
<div id="languageList" data-bind="with: viewModel">
<div id="languageListGrid" data-bind="kendoGrid: { data: languageViewModels, columns: [
{
field: 'Language',
title: 'Language',
width: 50
}
],
scrollable: false, sortable: true, pageable: false }" style="height: 380px">
</div>
</div>
</div>
javascript
$(function () {
var FranchiseDetailsViewModel = function () {
var
self = this,
initialize = function () {
self.languagesInfoViewModel(new LanguageListViewModel(self));
var parentViewModel = ({ viewModel: self.languagesInfoViewModel });
var element = $('div[data-viewId="languageList"')[0];
ko.applyBindings(parentViewModel, element);
};
FranchiseDetailsViewModel.prototype.languagesInfoViewModel = ko.observable();
initialize();
};
var LanguageListViewModel = function (franchise) {
var
self = this,
initialize = function () {
var languageViewModel = new LanguageDetailsViewModel(franchise);
self.languageViewModels.push(languageViewModel);
};
LanguageListViewModel.prototype.languageViewModels = ko.observableArray([]);
initialize();
};
var LanguageDetailsViewModel = function (franchise) {
LanguageDetailsViewModel.prototype.Language = ko.observable("English");
LanguageDetailsViewModel.prototype.franchise = franchise;
};
var initialize = new FranchiseDetailsViewModel();
});
This reference to the parent view model causes some kind of a infinitive loop when the grid is binding to the source data. I am receiving Maximum call stack size exceeded
error. I believe the error is in the kendo knockout library when binding to the source of the grid because if I remove the grid there are no errors on the knockout binding to the div on this line:
ko.applyBindings(parentViewModel, element);
Is this the real reason for this error and how can I fix this? I cannot remove the reference to the parent view model so my hope is to fix the kendo-knockout behavior when binding to the source data. Any help with working example will be greatly appreciated. Thanks.
Update per Niemeyer`s comment:
I have a div with some properties bound to FranchiseDetailsViewModel
. One of these properties represents a checkbox - name it isVisible
. I have another div with properties bound to LanguageDetailsViewModel
. Some of these properties are visible only if the checkbox of the FranchiseDetailsViewModel
is checked. That is franchise.isVisible
is true. This is the reason I need the franchise reference.
I am rather new to javascript and maybe I do not use the prototype property correctly. As I am instantiating my viewmodels with the new
keyword I found that when assigning it to the prototype they become public and are visible in the markup so I can bind them. From your example I see that this.myProperty also makes the property public. I am not sure if there is a difference in my scenario.
I decided to use this.myData.parent = parent;
as a solution to my problem. Thank You very much for your feedback.
Upvotes: 0
Views: 1031
Reputation: 114792
Based on the comment above:
One option is to "hide" franchise, so that Knockout doesn't recursively try to unwrap it. You can do this by making it a property of a function or observable (which is a function).
There are a few ways to do this:
var Child = function(parent) {
//use parent directly from the argument passed to the constructor. available as part of the closure.
this.myHandler = function() {
parent.log();
};
this.myData = ko.observable();
//reference as a sub-observable. you can bind against myData.parent, but it will disappear when doing ko.toJS/ko.toJSON
this.myData.parent = parent;
//similar to sub-observable. hide the actual value behind an empty function. It will not be found when doing ko.toJS/ko.toJSON.
this.parent = function() { };
this.parent.value = parent;
};
Example here: jsfiddle.net/rniemeyer/uSpZB.
Normally you would not want to put observables on the prototype, as they will be shared by all instances.
Upvotes: 1