Knockout ignore binding, for nested viewModels?

3,589 views
Skip to first unread message

Andrew Kharlamov

unread,
Mar 1, 2012, 7:05:45 PM3/1/12
to KnockoutJS
I think that is weird that you can have multiple viewModels on a page,
as long as they aren't nested. However, nested viewModels
automatically get scoped to the root viewModel via applyBindings.

For example:

applyBindings for this dom:
<div>
<label>root module</label>

applyBindings for this inner dom:
<div>
<label data-bind="text: innerModuleText"></label><!-- I am not
scoped to inner module, oh no what is innerModuleText? crash-->
</div>

</div>

Couldn't we have something that would stop applyBindings from
particular child elements:

applyBindings for this dom:
<div>
<label>root module</label>

applyBindings for this inner dom:
<div data-bind="ignoreRootBindings: true">
<label data-bind="text: innerModuleText"></label><!-- I am scoped
to inner module, yay! -->
</div>

</div>

What are your thoughts on this?

rpn

unread,
Mar 1, 2012, 8:49:08 PM3/1/12
to knock...@googlegroups.com
There are a couple ways that you can go on this one.

One choice is to create an overall view model that is a container for your sub view models.  

So, you would have:
var viewModel {
    subViewModelAname"Bob" },
    subViewModelBname"Ted" }    
};

ko.applyBindings(viewModel);

and you would can bind against it (with nested models) like:

<div data-bind="with: subViewModelA">
    <div data-bind="text: name"></div>
    <div data-bind="with: $root.subViewModelB">
        <span data-bind="text: name"></span>
    </div>
</div>

Another option is to create a simple binding that will stop KO from applyBindings to its children and then calling applyBindings with another model inside of it.

It would look like:
ko.bindingHandlers.stopBindings {
    initfunction({
        return 'controlsDescendantBindings'true };
    }        
};

var viewModelA name"Bob" };
var viewModelB name"Ted" };  

ko.applyBindings(viewModelA);
ko.applyBindings(viewModelBdocument.getElementById("inner"));

You would bind against it like:

<div>
    <div data-bind="text: name"></div>
    <div data-bind="stopBindings: true">
        <div id="inner">
            <span data-bind="text: name"></span>
        </div>        
    </div>
</div>


Hope this helps.

Andrew Kharlamov

unread,
Mar 2, 2012, 10:27:24 AM3/2/12
to KnockoutJS
That last solution works pretty well: http://jsfiddle.net/rniemeyer/MFnHj/

Wish that the viewModels were only checking stopBindings on their
childNodes, so we don't have to create that extra dom element. I will
have to muck around with knockout a little more and figure out how
this 'controlsDescendantBindings' flag works.

Thanks,
Andrew

scr...@gmail.com

unread,
Jul 27, 2012, 11:30:36 AM7/27/12
to knock...@googlegroups.com
I can't seem to get the 2nd example to work as a virtual element. I tried adding ko.virtualElements.allowedBindings.stopBindings = true;.

Is it possible?

Thanks,

Chris

rpn

unread,
Jul 27, 2012, 11:39:26 AM7/27/12
to knock...@googlegroups.com, scr...@gmail.com
Knockout 2.1 added the ability to specify custom bindings that work with virtual elements.  The previous fiddles reference KO 2.0.  Try updated to 2.1.

scr...@gmail.com

unread,
Jul 27, 2012, 11:42:36 AM7/27/12
to knock...@googlegroups.com, scr...@gmail.com
It works, I just made a mistake in my binding.

I always seem to put a colon after ko, like <!-- ko: stopBindings: true -->.

Chris
Reply all
Reply to author
Forward
0 new messages