1

In all of my knockout custom binding handlers, I always omit the update callback. My reasoning is that I can do all of the work I need to do inside of the init callback. In there, I can create computed's, call applyBindingsToNode (if I need) or setup manual subscriptions to subscribables and do my DOM manipulation inside those subscriptions.

My concern is that the default bindings in knockout are built using the update callback only.(Update: Not anymore, value and some other bindings only use init now) Is there any downside to doing all the work inside the init callback? Is there anything I'm missing? Thanks!

Allen Rice
  • 19,068
  • 14
  • 83
  • 115
  • 1
    It is not a problem to do so, and some of the built-in bindings after 3.0 now use that structure (`with`, `if`, and `ifnot` in 3.1 and `value` in 3.2, for example). Just remember to clean up: http://www.knockmeout.net/2014/10/knockout-cleaning-up.html – RP Niemeyer Oct 23 '14 at 20:24
  • Thanks Ryan, I appreciate the answer! I've been meaning to dive into the code to determine just how KO makes the determination to call the update callback. I'm guessing it just looks at what is observed within the init callback. For me, I prefer having very granular control over when updates are called. Also, most of the time my custom binding handelrs are just cleaning up large amounts of built in bindings. In those cases, I just end up using applyBindingsToNode anyway, and that should only be done in init. – Allen Rice Oct 23 '14 at 21:02
  • yes- `update` is wrapped in a computed and so it tracks dependencies accessed while it is being executed. So, if is fine to create your own computed to have greater control. Just pass the `disposeWhenNodeIsRemoved: element` option and/or use `ko.utils.domNodeDisposal.addDisposeCallback` (would be necessary to dispose of any manual subscriptions at least). – RP Niemeyer Oct 23 '14 at 21:11
  • Thanks, I've been using `addDisposeCallback` for a long time now. I've never seen anything for disposeWhenNodeIsRemoved, I'll go look some of that up now – Allen Rice Oct 23 '14 at 21:27
  • found info on disposeWhenNodeIsRemoved here http://www.knockmeout.net/2012/06/knockoutjs-performance-gotcha-3-all-bindings.html :) – Allen Rice Oct 23 '14 at 21:39
  • This one covers it too towards the end: http://www.knockmeout.net/2014/10/knockout-cleaning-up.html . Talks about your scenario. – RP Niemeyer Oct 23 '14 at 21:44

2 Answers2

1

Creating computeds and subscriptions in the init function, as you are doing, is completely supported in Knockout since version 3.0. It is a more advanced technique than using update since it means you need to take more care to ensure you're capturing and responding to all dependencies, as well as disposing subscriptions at the right time.

For reference, the update function itself is handled quite simply in Knockout (modified slightly for clarity):

var handlerUpdateFn = handler.update;
if (typeof handlerUpdateFn == "function") {
    ko.computed(
        function () {
            handlerUpdateFn(node, getValueAccessor(bindingKey), allBindings, 
                bindingContext.$data, bindingContext);
        },
        null,
        { disposeWhenNodeIsRemoved: node }
    );
}
Michael Best
  • 16,623
  • 1
  • 37
  • 70
  • Fantastic! So if you don't supply an update callback, knockout doesn't even create the computed? – Allen Rice Oct 23 '14 at 23:28
  • Superb, I was really hoping that was the case, you saved me a little bit of digging :) Thanks! Loving 3.2 btw – Allen Rice Oct 23 '14 at 23:35
  • Regardless of whether or not this is supported, there's no need to complicate things in most cases. The question does not imply more granular control is needed. The question asks if there is anything wrong with doing what could be done in the update in the init instead. I still think the answer to that question is yes, it is wrong. If you can use the built-in update, there's no reason to complicate things, since as Michael said, " you need to take more care to ensure you're capturing and responding to all dependencies". There's no need to add this complexity and risk in most cases. – wired_in Oct 24 '14 at 15:23
  • Those are definitely caveats to be aware of. For the most part, my custom bindings consist of manually calling applyBindingsToNode with a lot of bindings that I don't want to clutter up my html. That sort of work should only be done in init anyway. – Allen Rice Oct 24 '14 at 16:48
0

You are replacing the update mechanism of the binding handler with computeds and subscriptions, so yes this is clearly not best practice when creating custom binding handlers, otherwise there would be no update function.

Other than violating best practices, you are just creating more overhead with added subscriptions and computeds that aren't needed. The binding handler flow will be executed for you. Knockout is already evaluating the expression sent in to the binding handler and executing the update function for you. So you are in addition to that, adding computeds and subscriptions which could very well cause unexpected behavior. There may be instances where this could be necessary to some degree, but not using the built-in update mechanism at all can only cause problems and confusion.

wired_in
  • 2,593
  • 3
  • 25
  • 32