0

I have a knockout custom binding called groupedOptions which binds the options of a select list with optgroups. This does the same as the standard options binding but includes logic to handle options groups.

The binding worked fine under knockout v2.3 but stopped working after upgrading to v3.3. After the update it would no longer bind the value correctly.

Having a look at the source for the value binding in the new version it has some code to tell it to run after the options binding:

ko.bindingHandlers['value'] = {
  'after': ['options', 'foreach'],
  'init': function (element, valueAccessor, allBindings) {
    ...

Changing this to:

ko.bindingHandlers['value'] = {
  'after': ['options', 'foreach', 'groupedOptions'],
  'init': function (element, valueAccessor, allBindings) {
    ...

Will work but seems a bit hacky to me. Does anyone have any idea of what the best practice way to do this is.

In other words: if I have a custom binding that needs to be run before a binding that is defined in knockout how would I do it without editing the knockout source?

Jeroen
  • 60,696
  • 40
  • 206
  • 339
Gunner
  • 907
  • 2
  • 9
  • 17
  • Can you post the code of your `groupedOptions` binding handler? – nemesv Dec 21 '15 at 12:44
  • Second @nemesv. I've answered the actual question ("how to run custom bindings before default bindings"), but fear you have an [XY-problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) and you should probably be looking at fixing/changing your custom binding itself. – Jeroen Dec 21 '15 at 12:59
  • the groupedOptions binding is a copy and paste of the options, it is the solution from onuralp from this question http://stackoverflow.com/questions/8972367/knockoutjs-select-with-option-group. So it is indeed kind of an XY problem, when I've googled for this i've seen people either editing the knockout binding directly to support grouping, doing it with a foreach (which is cumersom if you have many dropdowns requiring grouping). The downside of the approach I've taken is every knockout version update requires this to be re-implemented, but we're not duplicating foreaches. – Gunner Dec 21 '15 at 14:56

1 Answers1

1

The bottom line contains the actual question:

If I have a custom binding that needs to be run before a binding that is defined in knockout, how would I do it without editing the knockout source?

Just like so:

ko.bindingHandlers['value'].after = ko.bindingHandlers['value'].after.concat('customBinding');

See it (indirectly) at work here:

ko.bindingHandlers['customBinding'] = {
  init: function() { console.log("The `customBinding` was initialized."); }
};

ko.bindingHandlers['value'].after = ko.bindingHandlers['value'].after.concat('customBinding');

console.log(ko.bindingHandlers['value'].after);

ko.applyBindings({
  // *pure* computed, or else it would be evaluated once straight away
  myObs: ko.pureComputed(function() { console.log("The `value` binding was initialized."); })
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<input data-bind="customBinding, value: myObs">

PS. Are you sure you don't have an XY-problem?

Jeroen
  • 60,696
  • 40
  • 206
  • 339