1

I have a custom binding, that has implemented update.

I would like to know what the value was before update was called. I can not see that it is passed into any of the parameters. Have i missed it?

    ko.bindingHandlers.ticker= {
        update: function (element, valueAccessor, allBindingsAccessor) {
            var toNumber = ko.utils.unwrapObservable(valueAccessor());
            var fromNumber = 0; //<---- can i set this to the old value?

            var counter = new Ticker(element, fromNumber, toNumber);

            counter.start();
        }
    }

Currently i am counting from 0 to the value (this is simply animated in the UI) but i would like to be able to count from the old value to the new value instead of it resetting to 0 and then counting from there.

4imble
  • 13,979
  • 15
  • 70
  • 125
  • 1
    I don't believe it's passed in. Perhaps you could store it as a property on the element, so it's still there the next time `update` runs? – James Thorpe Apr 14 '15 at 13:39
  • Should be fine, since you have the likes of jQuery-type plugin binding handlers that update plugin options on the element on an `update` – James Thorpe Apr 14 '15 at 14:19
  • Also, because you're creating a new `Ticker()` inside the binding, you actually do the same as what `ko.components` does with the function provided to `viewModel`, but with the disadvantage that you cannot access JS properties afterwards. Although this approach is perfectly valid, to me it seems more consistent & in line with the MV* pattern to store *all* model data in JS, as opposed to inside DOM attributes. – webketje Apr 14 '15 at 14:30

2 Answers2

2

There are two ways to do this:

1) Use ko.utils.domData API to store some data with your element.

// Read previous data
var prevData = ko.utils.domData.get(element, 'dataKey');
var newData = 42;

// Remember data for next time update is called
ko.utils.domData.set(element, 'dataKey', newData);

2) Do not use update at all. Everything you do with update you can also do with a computed or a simple subscription.

ko.bindingHandlers.ticker = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var toNumber = ko.utils.unwrapObservable(valueAccessor());
        var fromNumber = 0;        

        function startTicker(toNumber) {
            var counter = new Ticker(element, fromNumber, toNumber);
            counter.start();
            fromNumber = toNumber;
        }

        ko.computed(function () {
            startTicker(toNumber);
        }, null, { disposeWhenNodeIsRemoved: element });
    }
}

Note the computed will be safely disposed if your dom node is removed.

Olga
  • 1,648
  • 1
  • 22
  • 31
1

Assuming that the ticker will be updating the element value from fromNumber to toNumber, you could just implement this as an observable and then use the text binding to update the element. If the ticker is purely for the UI and its state shouldn't be reflected in the model, then consider consuming an object instead of an observable for the valueAccessor(), taking the from and to in that way.

If you still need to have the original state, then you could also use the init of the binding to capture the original value.

Nick Caballero
  • 944
  • 1
  • 8
  • 19