JSFiddle - React, Tailwind, and code Playground
HTML
<script src="http://andersmalmgren.github.io/Knockout.Concurrency/src/knockout.concurrency.js"></script>
<div><input data-bind="value: name"</input></div>
<div data-bind="foreach: children">
<div><input data-bind="value: name"></input><span data-bind="concurrency: concurrency"></span></div>
</div>
<button data-bind="disable: hasConflicts">Save</button>
<button data-bind="click: resolve, visible: hasConflicts">Resolve conflicts</button>
<button data-bind="click: getData">Simulate new save event from backend</button>
CSS
span.concurrency
{
background: no-repeat url(https://github.com/AndersMalmgren/Knockout.Concurrency/raw/master/Knockout.Concurrency.Demo/Content/images/icons/warning-16.png);
padding: 2px 0 2px 16px
}
span.concurrency button
{
width: 16px;
height: 16px;
border: none;
background: transparent;
margin-left: 2px;
cursor: pointer;
}
span.concurrency button.take-local {
background-image: url(https://github.com/AndersMalmgren/Knockout.Concurrency/raw/master/Knockout.Concurrency.Demo/Content/images/icons/resolve-16.png)
}
span.concurrency button.take-server {
background-image: url(https://github.com/AndersMalmgren/Knockout.Concurrency/raw/master/Knockout.Concurrency.Demo/Content/images/icons/merge-16.png)
}
JavaScript
ViewModel = function() {
this.name = ko.observable("John").extend({ concurrency: true});
this.children = ko.observableArray().extend({ concurrency: { autoInjectViewForArrays: false }});
this.concurrencyRunner = new ko.concurrency.Runner(this);
this.hasConflicts = ko.computed(function() {
return this.concurrencyConflicts().length > 0;
}, this);
this.resolve = function() {
this.concurrencyRunner.takeServer();
}
this.createChild = function(id, name) {
return { id: id, name: ko.observable(name).extend({concurrency: true})};
}
this.getData = function() {
//Simulate backend data
var data = { name: "John2", children: [{ id: 1, name: "Jane"},{ id: 3, name: "Donald Duck"}]};
var createChild = this.createChild;
var mappings = {
children: {
key: function(item) {
return ko.utils.unwrapObservable(item.id);
},
create: function(data) {
return createChild(data.id, data.name);
}
}
};
this.concurrencyRunner.run(this, data, mappings);
}
this.children.push(this.createChild(1, "Jane Doe"));
this.children.push(this.createChild(2, "Uncle Scrooge"));
}
ko.applyBindings(new ViewModel());