JSFiddle - React, Tailwind, and code Playground
HTML
<div>
<label>id:</label><input data-bind="value: id" />
</div>
<div>
<label>name:</label><input data-bind="value: name" />
</div>
<br />
<button data-bind="click: justMap">Just map</button>
<button data-bind="click: mapWithPause">Map with pause</button>
<br />
<br />
<div data-bind="foreach: updates">
<div data-bind="text: $data"></div>
</div>
CSS
label
{
width: 60px;
display: inline-block;
}
JavaScript
ko.utils.pausableObservable = function(state) {
var observable = ko.observable(state);
var pending = [];
observable.pushNotification = function(object, conf, args) {
if (!conf.pushed)
{
conf.pushed = true;
pending.push({ object: object, conf: conf, args: args });
}
};
observable.subscribe(function(newValue) {
if (!newValue)
{
var pendingCache = pending;
pending = [];
ko.utils.arrayForEach(pendingCache, function(item) {
item.conf.pushed = false;
});
ko.utils.arrayForEach(pendingCache, function(item) {
item.object.notifySubscribers.apply(item.object, item.args);
});
}
});
return observable;
};
ko.extenders.pausable = function(target, pausable) {
var oldNotifySubscribers = target.notifySubscribers;
var conf = { pushed: false };
target.notifySubscribers = function(value, event) {
if (pausable.peek())
{
if (!event)
pausable.pushNotification(target, conf, arguments);
}
else
oldNotifySubscribers.apply(target, arguments);
};
return target;
};
function ViewModel()
{
var self = this;
self.mapping = ko.utils.pausableObservable(false);
self.id = ko.observable("a1").extend({ pausable: self.mapping });
self.name = ko.observable("b1").extend({ pausable: self.mapping });
self.updates = ko.observableArray([]);
self.id.subscribe(function() {
var id = self.id();
var name = self.name();
self.updates.unshift(id + ", " + name);
});
}
ViewModel.prototype.justMap = function()
{
var self = this;
var next = parseInt(self.id().substring(1)) + 1;
self.id("a" + next);
self.name("b" + next);
};
ViewModel.prototype.mapWithPause = function()
{
var self = this;
self.mapping(true);
self.justMap();
self.mapping(false);
};
ko.applyBindings(new ViewModel());