Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout.js - cannot wrap 'with', 'foreach' and other template bindings

I am trying to create a custom binding that wraps an existing binding, namely the "with" or "foreach" bindings that are built into Knockout.

Unfortunately in doing so I get the following error: Uncaught TypeError: Cannot call method 'createChildContext' of undefined from knockout-latest.debug.js:3060 (the problem also exhibits on version 2.1.0).

I have reproduced the exception on jsFiddle, with Google Chrome 21.0.1180.57.

The custom binding is simply defined as follows:

ko.bindingHandlers.myWith = {
    init: function(element, valueAccessor, allBindings, viewModel) {
        // do things
        return ko.bindingHandlers.with.init(element, valueAccessor,
                                            allBindings, viewModel);
    },

    update: function(element, valueAccessor, allBindings, viewModel) {
        return ko.bindingHandlers.with.update(element, valueAccessor, 
                                              allBindings, viewModel); 
    }
};

One would expect to be able to "wrap" the existing bindings with a simple handler in the form above, much like it is discussed in this article.

like image 348
Brian M. Hunt Avatar asked Dec 16 '22 20:12

Brian M. Hunt


1 Answers

In KO 2.0, binding handlers actually take in a 5th argument that is the binding context. The binding context holds things like $data, $parent, $parents, $root.

So, you just need to forward that parameter on like:

ko.bindingHandlers.myWith = {
    init: function(element, valueAccessor, allBindings, viewModel, context) {
        // do things
        return ko.bindingHandlers.with.init(element, valueAccessor,
                                            allBindings, viewModel, context);
    },

    update: function(element, valueAccessor, allBindings, viewModel, context) {
        return ko.bindingHandlers.with.update(element, valueAccessor, 
                                              allBindings, viewModel, context); 
    }
};

http://jsfiddle.net/rniemeyer/48uJg/2/

or

ko.bindingHandlers.myWith = {
    init: function() {
        return ko.bindingHandlers.with.init.apply(this, arguments);
    },

    update: function() {
        return ko.bindingHandlers.with.update.apply(this, arguments);
    }
};
like image 171
RP Niemeyer Avatar answered Apr 30 '23 03:04

RP Niemeyer