How to use computed.subscribe to toggle smart dirty flag
http://www.knockmeout.net/2011/05/creating-smart-dirty-flag-in-knockoutjs.html
by Semmel
HTML
<script src="http://knockoutjs.com/downloads/knockout-2.3.0.js"></script>
<script src="http://underscorejs.org/underscore.js"></script>
string:<input data-bind="value: string"/><br><input type="text"/><br>
switched:<input type="checkbox" data-bind="checked: switched"/><br>
list:<div data-bind="foreach:items">
<div data-bind="text:name"></div>
</div>
isDirty:<input type="checkbox" data-bind="checked: isDirty" disabled="disabled" />
<textarea id="out" cols="20" rows="20" disabled="disabled"></textarea>
CSS
li { padding: 2px; margin: 2px; }
input { width: 75px; }
.dirty { border: solid yellow 2px; }
JavaScript
//not used in this example. one time flag, that drops its subscriptions after the first change.
function log(text)
{
document.getElementById('out').value += text + "\n";
console.log(text);
}
ko.basicDirtyFlag = function(root) {
var _isDirty = ko.observable(false);
var _initialState = ko.observable(ko.toJSON(root));
var result = ko.computed({
read: function()
{
//once we detected a change we can give up subscriptions
// and depend solely on the internal boolean _isDirty
if (!_isDirty())
{
//just for subscriptions
var resultFlag = ko.toJSON(root) !== _initialState();
log("subscribing..");
log("returning " + resultFlag);
return resultFlag;
}
log("returning " + _isDirty() + '\n');
return _isDirty();
},
write: function(value)
{
if (value === false && _isDirty() === true)
{
/// reset the flag
_initialState(ko.toJSON(root));
log("updating internal obs with " + value + "...");
_isDirty(value);
log("..done");
toggle2TrueSub = result.subscribe(toggle2True);
}
else if (value === true)
{
log("updating internal obs with " + value + "...");
_isDirty(true);
log("..done");
//throw new Error("not supported yet");
}
}
}
);
function toggle2True()
{
log("change in root..");
if (!_isDirty())
{
toggle2TrueSub.dispose();
log("toggling flag.");
_isDirty(true);
}
log("\n");
}
var toggle2TrueSub = result.subscribe(toggle2True);
return result;
}
var ViewModel = function()
{
this.string...