Multiple Extenders in Knockout JS not working

2019-06-21 16:10发布

Just finding my way in KO, so please be gentle!

Individually each extender works, but when i chain them, the first one (reset) doesnt fire.

Javascript:

ko.extenders.reset = function (target) {
    var initialValue = target();

    target.reset = function () {
        target(initialValue);
    }

    return target;
}
ko.extenders.numeric = function (target, precision) {
    //create a writeable computed observable to intercept writes to our observable
    var result = ko.computed({
        read: target, //always return the original observables value
        write: function (newValue) {
            var current = target(),
                roundingMultiplier = Math.pow(10, precision),
                newValueAsNum = isNaN(newValue) ? 0 : parseFloat(+newValue),
                valueToWrite = Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier;

            //only write if it changed
            if (valueToWrite !== current) {
                target(valueToWrite);
            } else {
                //if the rounded value is the same, but a different value was written, force a notification for the current field
                if (newValue !== current) {
                    target.notifySubscribers(valueToWrite);
                }
            }
        }
    }).extend({
        notify: 'always'
    });

    //initialize with current value to make sure it is rounded appropriately
    result(target());

    //return the new computed observable
    return result;
};

function AppViewModel(first, last) {
    this.firstName = ko.observable(first).extend({
        reset: true

    });
    this.lastName = ko.observable(last).extend({
        reset: true,
        numeric: 0
    });
    self.resetAll = function () {
        for (key in self) {
            if (ko.isObservable(self[key]) && typeof self[key].reset == 'function') {
                self[key].reset()
            }
        }
    }
}

ko.applyBindings(new AppViewModel());

HTML:

1 extender (works):<input data-bind='value: firstName' /><br>
2 extenders (doesnt work)<input data-bind='value: lastName' /><br>
<input type="button" value="Reset All" data-bind="click:resetAll" id="ResetInvoiceButton" />

Fiddle:

http://jsfiddle.net/sajjansarkar/vk4x2/1/

1条回答
对你真心纯属浪费
2楼-- · 2019-06-21 16:47

Because your numeric extender returns a new computed the order of your extenders does matter.

In your current setup your reset extender runs first and it adds the reset function to your original observable but then the numeric runs so it overrides your "reset enhanced" observable with a completely new computed observable.

So you just need to execute your extenders in the correct order:

this.lastName = ko.observable(last)
                  .extend({ numeric: 0 })
                  .extend({ reset: true });

Demo JSFiddle.

Note that if you want to have a specific order for your extenders you need to apply them in separate extend calls otherwise the execution order is not guarantied to be in the order of the properties.

查看更多
登录 后发表回答