Reputation: 3851
I am currently experimenting with SPAs and the structure of my first app roughly follows the pattern described in the upcoming book Single Page Web Applications by Mikowski/Powell: The app consists of modules which are nested into each other. One root module has one or more sub-modules, each of those might have one or more sub-modules of its own. To add the sub-modules to the DOM, the parent modules provides a (jQuery-)element to the child to which it attaches its own markup. Other than that the modules are more or less completely isolated and how they function doesn't matter to the rest of the SPA. Each modules resides in its own file and dependencies are resolved using require.js (the book imports them manually).
Now I'd like to use knockout.js to render some of the modules, but I'm rather new to ko, so I'm wondering: Imagine a top-level module has several sub-modules attached. It uses knockout.js to do its binding while one of the sub-modules does too but another one doesn't. each of course has it's own model data.
One example that might illustrate the question rather well is that of a "tabbed panel": The parent has several tabs and uses knockout to determine which tab is currently visible. Each of the tabs is a module by itself that can have arbitrarily complex markup/functionality itself and should therefore be encapsulated in its own file/module.
Upvotes: 4
Views: 1802
Reputation: 114792
You will not want to call ko.applyBindings
on a parent element and then on one of its child elements. Elements will get bound twice, although in most cases you will just get errors, as the child may be trying to bind against a different context.
A couple choices:
1-If the elements don't overlap, then you can call ko.applyBindings
and specify a second argument that is a DOM element to use as the root element. This would look like:
ko.applyBindings(viewModelOne, document.getElementById("one"));
ko.applyBindings(viewModelTwo, document.getElementById("two"));
2-In your question though, it seems that Knockout would be managing the tabs and the content of each tab where the individual tabs might be child elements. One choice is to create an overall view model that contains your sub view models like:
var ViewModel = function() {
this.tabs = ko.observableArray();
this.selectedTab = ko.observable();
};
The "tab" objects can then contain their own view models. It could be something like: http://jsfiddle.net/rniemeyer/PctJz/
3-A additional alternative is described here: http://www.knockmeout.net/2012/05/quick-tip-skip-binding.html. This technique allows you to bind a view model against the entire page, but then carve out areas that you want to bind separately with calls to ko.applyBindings
with a DOM element as the second argument.
Upvotes: 7