Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How might I cancel a change to an observable array w/ Knockout 3.0?

I have a change occurring to an array. I am using Sanderson's latest array subscription method to catch the add/delete change. In this subscription is where I intend to bundle and send my request over the wire. If the request fails for any reason I want to be able to cancel any possible changes to the collection. I have verified that this subscription is hit before the change propagates so I assume there would be a way to say "STOP DON'T DO IT" however I can't figure out how.

As my example...

self.SourceData = ko.observableArray(data);
self.SourceData.subscribe(function(changes) {
    var isAllGood = true;
    ko.utils.arrayForEach(changes, function(ch) {
        if (ch.value == doesNotMeetMyCondition) isAllGood = false;
    });
    if (!isAllGood) <STOP DON'T DO IT>
}, null, 'arrayChange');

When inspecting 'this' I do see the ko.subscription object with the standard [callback, dispose, disposeCallback, target] but nothing seems to amount to STOP DON'T DO IT.

Any thoughts would be quite helpful. Thanks.

like image 793
beauXjames Avatar asked Dec 19 '13 20:12

beauXjames


People also ask

What is observable array in knockout JS?

An observableArray just tracks which objects it holds, and notifies listeners when objects are added or removed.

How do I assign a value to knockout observable?

To create an observable, assign the ko. observable function to the variable. A default value can be specified in the constructor of the call. Knockout then converts your variable into a function and tracks when the value changes, in order to notify the UI elements associated with the variable.

What is observable in knockout?

observable function to a variable. Knockout then converts the variable into a function and tracks when the value changes to notify the UI elements associated with the variable.


2 Answers

There is not currently a way to stop the change from going through.

You could potentially subscribe to the beforeChange event and cache a copy of the array before the change. Something like:

self.SourceData.subscribe(function(value) {
    /store copy, in case it needs to be restored
    self.beforeSourceData = value && value.slice();
}, null, "beforeChange");
like image 185
RP Niemeyer Avatar answered Nov 17 '22 13:11

RP Niemeyer


You can use another approach - create extender to validate your array on change. I've created simplified example that checks simple array of integers for specified upper boundary. Fiddle: http://jsfiddle.net/pkutakov/n2APg/1/ Code:

ko.extenders.checkValue=function (value, condition){
    var result=ko.computed({
        read: value,
        write: function (newValue){
            var current=value();
            var canSave=true;
            ko.utils.arrayForEach(newValue, function(ch) {
                if (ch>condition)
                    canSave=false;
            });
            if (canSave)
            {
                value(newValue);
                value.notifySubscribers(newValue);
            }
            else
                value.notifySubscribers(value());
        }
    }).extend({ notify: 'always'});
    result(value());

    //return the new computed observable
    return result;
}

function AppViewModel(data)
{
    self=this;
    self.Data=ko.observableArray(data).extend({ checkValue: 100});
}

var mydata=[10, 11];
ko.applyBindings(new AppViewModel(mydata));
like image 30
Pavel Kutakov Avatar answered Nov 17 '22 13:11

Pavel Kutakov