Question

I'm having an issue applying custom binding handlers when using knockout with requireJS. Basically, in the past I've included a global binding-handler js file that contains all my custom bindings. Now that I'm using requireJS to enforce dependencies, I'm not sure how to access these custom bindings.

I used to do create the global functions with

function KOCustomBindings() {
// Custom Bindings
ko.bindingHandlers.returnKey = {
//handler code
}
}

Now that I'm using require, I feel as if I should have a define statement

define(['jquery', 'knockout'],
    function($, ko)){
// Custom Bindings
return KOCustomBindings;
}
});

However, I don't believe the bindings will execute unless specifically called, perhaps in a shim? Does anyone have any ideas on this?

Thanks for your help,

Was it helpful?

Solution

Since custom bindings modify the ko object, they only need to be loaded once, and their modules do not need to return anything. If you have a main/entry/app section as the first step in your app, simply requiring your custom bindings and extenders is all you need to do.

define(['jquery', 'knockout'], function($, ko)){
    // Custom Bindings
    ko.bindingHandlers.returnKey = { ... }

    //NO return needed
});

Then, in your startup section, just

require('lib/custom-ko-bindings');

OTHER TIPS

An easy way to do this is to define your custom binding as an AMD module and require it from your parent viewmodel. Example -

Bindings.js

define(, function () {
    ko.bindingHandlers.Date = {
        update: function (element, valueAccessor) {
            var value = valueAccessor();
            var date = moment(value());
            var strDate = date.format('MM-DD-YYYY');
            $(element).text(strDate);
        }
    };
});

Your viewmodel -

define(['jquery', 'knockout', 'bindings'],
    function($, ko, bindings)){
});

This will give any element in your DOM access to the Knockout binding handler of 'Date' for example. (My example is one that I have used with moment.js)

In any child views or views that require your parent view model now you should be able to use

<span data-bind="Date: myDate" />

I was able to achieve this by wrapping knockout in my bindings module and returning the modified knockout instance. Here is the config I ended up with:

require.config({
  paths: {
    'knockout': 'lib/knockout', // name that's only used once in customBindings.js
    'ko': 'app/customBindings'
  }
  // more config ommitted
});

My custom bindings:

define(['knockout'], function (ko) {
    ko.bindingHandlers.returnKey = {
        //handler code
    }
    return ko;
});

And my modules that require knockout only need to reference 'ko'.

require(['jquery', 'ko', 'underscore'], function ($, ko, _) {
    // do knockout-y things! now with bindings!
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top