Inheriting Viewmodels
HTML
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-min.js"></script>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css">
<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>
<div data-bind="foreach: items">
<div data-bind="css: { 'label label-important' : dirtyFlag.isDirty }">
<input data-bind="value: name, valueUpdate: 'afterkeydown'" />
<button class="btn" data-bind="click: dirtyFlag.reset">Save</button>
</div>
</div>
Dirty Items: <span data-bind="text: dirtyItems().length"></span>
JavaScript
ko.dirtyFlag = function(root, isInitiallyDirty) {
var result = function() {},
_initialState = ko.observable(ko.toJSON(root)),
_isInitiallyDirty = ko.observable(isInitiallyDirty);
result.isDirty = ko.computed(function() {
return _isInitiallyDirty() || _initialState() !== ko.toJSON(root);
});
result.reset = function() {
_initialState(ko.toJSON(root));
_isInitiallyDirty(false);
};
return result;
};
function Item(data) {
this.id = ko.observable(data.id);
this.name = ko.observable(data.name);
this.dirtyFlag = new ko.dirtyFlag(this);
}
var BaseViewModel = function () {
var self = this;
self.items = ko.observable([]);
self.newItem = {};
self.dirtyItems = ko.computed(function () {
return self.items().filter(function (item) {
return item.dirtyFlag.isDirty();
});
});
self.isDirty = ko.computed(function () {
return self.dirtyItems().length > 0;
});
self.load = function () { }
};
var ViewModel = function(data) {
var self = this;
BaseViewModel.call(self);
var items = ko.utils.arrayMap(data, function(i) { return new Item(i); });
self.items(items);
};
ViewModel.prototype = new BaseViewModel();
var init = [
{ id: 1, name: "Guy" },
{ id: 2, name: "Dude" }
]
window.vm = new ViewModel(init);
ko.applyBindings(window.vm);