Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I rebind the knockout viewmodel when the page is loaded in as a partial via ajax?

The page that I'm working with has a couple tabs and the content of each tab is loaded in via ajax by requesting a partial view from the controller. The problem is that the partial view uses knockoutjs, so it is bound to a view model. In this particular scenario, the page is loaded up in its entirety first time through, so all of the bindings work fine. When you switch tabs, it requests a partial view and replaces the tab content area with the new page. When you switch back to the first tab, it'll successfully loads the partial, except it would appear that all of the knockout bindings have been lost so there is a lot of missing data.

I can't place the viewmodel declaration and model bind in the partial because jquery hasn't been loaded by that point. Or so it would seem ($ is not defined).

The view model is declared and bound on the main page that calls the partial view(s), not the partial view itself, so I thought the model would still be available and bind successfully, but it does not. I know I'm doing this wrong, and partial view are super wonky when it comes to javscript so I'm hoping to steal a bit of insight from you guys.

Here's the basic setup: enter image description here

like image 806
Sinaesthetic Avatar asked Jan 20 '14 20:01

Sinaesthetic


1 Answers

If you are able to bind to specific non-overlapping areas of the page, then you could choose to call ko.applyBindings(someViewModel, someDomElement) like in this answer: Can you call ko.applyBindings to bind a partial view?

However, if you have an overall view model bound to the page and then "islands" of content that are loaded via a partial that you want to bind later, then one option would be to go for something like this: http://www.knockmeout.net/2012/05/quick-tip-skip-binding.html. So, you would set up a binding on the container of where your partial goes that tells Knockout to keep its hands off of that area. Then when you load the partial, you can safely call ko.applyBindings(someViewModel, innerContainer).

The binding might look like:

ko.bindingHandlers.stopBinding = {
    init: function() {
        return { controlsDescendantBindings: true };
    }
};

and you would use it like:

<div id="outerContainer" data-bind="stopBinding: true">
    <div id="innerContainer">
     ...load your partial here
    </div>
</div>

Then, ko.applyBindings(someViewModel, document.getElementById("innerContainer"));

like image 192
RP Niemeyer Avatar answered Nov 01 '22 02:11

RP Niemeyer