Inspired by implementation of pauseableComputed and observable withPausing I have created pauseableObservable and pauseableObservableArray that have abilities to stop notifications to subscribers and than resume when needed. Also it work recursively for all nested pauseable properties.
You can play with it HERE on Codepen.
PauseableObservable:
// PauseableObservable - it's observable that have functions to 'pause' and 'resume' notifications to subscribers (pause/resume work recursive for all pauseable child).
ko.isPauseableObservable = function(instance) {
return ko.isObservable(instance) && instance.hasOwnProperty("pause");
}
ko.pauseableObservable = function(value) {
var that = ko.observable(value);
function getPauseableChildren() {
var currentValue = that();
var properties = Object.getOwnPropertyNames(currentValue);
var pauseables = properties.filter((property) => {
return ko.isPauseableObservable(currentValue[property]);
});
return pauseables.map((property) => {
return currentValue[property];
});
}
that.pauseNotifications = false;
that.isDirty = false;
that.notifySubscribers = function() {
if (!that.pauseNotifications) {
ko.subscribable.fn.notifySubscribers.apply(that, arguments);
}
that.isDirty = that.pauseNotifications;
};
that.pause = function() {
that.pauseNotifications = true;
var pauseableChildren = getPauseableChildren();
pauseableChildren.forEach((child) => { child.pause(); });
}
that.resume = function() {
that.pauseNotifications = false;
if (that.isDirty) {
that.valueHasMutated();
}
var pauseableChildren = getPauseableChildren();
pauseableChildren.forEach((child)=> { child.resume(); });
}
return that;
}
PauseableObservableArray
// PauseableObservableArray - it's observable array that have functions to 'pause' and 'resume' notifications to subscribers about add/remove items.
// In case if array items pauseable observables - run recursively run 'pause'/'resume' on them.
ko.pauseableObservableArray = function(items) {
var that = ko.observableArray(items);
that.pauseNotifications = false;
that.isDirty = false;
that.lastNotification = [];
that.notifySubscribers = function() {
if (!that.pauseNotifications) {
ko.subscribable.fn.notifySubscribers.apply(that, arguments);
} else {
that.lastNotification = arguments;
}
that.isDirty = that.pauseNotifications;
};
that.pause = function () {
var items = that();
that.pauseNotifications = true;
items.forEach(function(item) {
if(ko.isPauseableObservable(item)) {
item.pause();
}
});
}
that.resume = function () {
var items = that();
that.pauseNotifications = false;
if(that.isDirty) {
ko.subscribable.fn.notifySubscribers.apply(that, that.lastArguments);
}
items.forEach(function(item) {
if(ko.isPauseableObservable(item)) {
item.resume();
}
});
}
that.refresh = function () {
that.resume();
that.pause();
}
return that;
}
Usage example:
var firstItem = ko.pauseableObservable("Hello");
var secondItem = ko.pauseableObservable("World");
var items = [
firstItem,
secondItem
];
var array = ko.pauseableObservable(items);
// Stop notifications from specific observable
firstItem.pause();
// Change won't raise notification to subscribers
firstItem("Hi");
// Resume notifications
firstItem.resume();
// Stop notifications from all items of array
array.pause();
// Change won't raise notification to subscribers
array.push("Hey");
array()[0]("Hi");
// Resume notifications
array.resume();