Reputation: 8937
I have a checkbox bound to an observable on a view model. I have a requirement to essentially pop up an "Are you sure?" confirmation prompt if the user changes it from true to false. I'm having a horrible time figuring out the best place to make the change "cancelable" . . .
1) jQuery handler for click event 2) Viewmodel internal subscribe "beforeChange" 3) Viewmodel internal subscribe (normal)
In any case, I'd vastly prefer to have the chance to cancel the change outright than react to the change, potentially reverting it back to its previous value if need be.
Does Knockout's subscribe event give you the chance to cancel a change? Any insight would be appreciated. Thanks!
Upvotes: 12
Views: 8691
Reputation: 15570
Because of the problems commented in @RP Niemeyer answer, I've just implemented this extender:
ko.extenders.confirmable = function(target, options) {
var message = options.message;
var unless = options.unless || function() { return false; }
//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();
//ask for confirmation unless you don't have
if (unless() || confirm(message)) {
target(newValue);
} else {
target.notifySubscribers(current);
}
}
}).extend({ notify: 'always' });
//return the new computed observable
return result;
};
You can then apply that to your model like this:
var viewModel = {
myvalue: ko.observable(false).extend({confirmable: "Are you sure?"});
}
And, if there was a case in which not to ask for confirmation (in this silly example, we'll skip confirmation during March), you can do:
var viewModel = {
myvalue: ko.observable(false).extend({confirmable: { message: "Are you sure?", unless: function() { return new Date().getMonth() == 2 }} });
}
Upvotes: 15
Reputation: 114792
Here is a simple option using jQuery's stopImmediatePropagation:
http://jsfiddle.net/rniemeyer/cBvXM/
<input type="checkbox" data-bind="click: confirmCheck, checked: myvalue" />
js:
var viewModel = {
myvalue: ko.observable(false),
confirmCheck: function(data, event) {
if (!confirm("Are you sure?")) {
event.stopImmediatePropagation();
return false;
}
return true;
}
};
Upvotes: 22