JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://github.com/downloads/SteveSanderson/knockout/knockout-2.1.0.debug.js"></script>
<script src="https://github.com/downloads/rniemeyer/knockout-sortable/knockout-sortable.js"></script>
<div class="grid_6">
<ul id="routes" data-bind="sortable:{data: routes, afterMove: myDropCallback}">
<li>
<h2 data-bind="text: $data"></h2>
<ul class="routeTasks" data-bind="foreach: $root.routeGroups.index.routeId()[$data]">
<li><div data-bind="text: customerName"></div></li>
</ul>
</li>
</ul>
</div>
<div class="grid_6">
<ul id="scheduledtasks" data-bind="sortable:{data: scheduledTasks, afterMove: myDropCallback}">
<li data-bind="text: customerName">
</li>
</ul>
</div>
JavaScript
ko.observableArray.fn.distinct = function(prop) {
var target = this;
target.index = {};
target.index[prop] = ko.observable({});
ko.computed(function() {
//rebuild index
var propIndex = {};
ko.utils.arrayForEach(target(), function(item) {
var key = ko.utils.unwrapObservable(item[prop]);
if (key) {
propIndex[key] = propIndex[key] || [];
propIndex[key].push(item);
}
});
target.index[prop](propIndex);
});
return target;
};
var Task = function(id, routeId, routeName, customerName) {
this.id = ko.observable(id);
this.routeId = ko.observable(routeId);
this.routeName = ko.observable(routeName);
this.customerName = ko.observable(customerName);
};
var ViewModel = function() {
var self = this;
self.tasks = ko.observableArray([
new Task(1, 1, "Route 1", "Cust 1"),
new Task(2, 1, "Route 1", "Cust 2"),
new Task(3, 2, "Route 2", "Cust 3"),
new Task(4, 2, "Route 2", "Cust 4"),
new Task(5, 3, "Route 3", "Cust 5")
]);
self.scheduledTasks = ko.observableArray([
new Task(8, 4, "Route 4", "Cust 8"),
new Task(9, 4, "Route 4", "Cust 9"),
new Task(10, 5, "Route 5", "Cust 10")
]);
self.routeGroups = self.tasks.distinct('routeId');
self.routes = ko.dependentObservable(function() {
var route = ko.utils.arrayMap(this.tasks(), function(item) {
return item.routeId();
});
return ko.utils.arrayGetDistinctValues(route).sort();
}, self);
self.myDropCallback = function(arg) {
console.log(arg);
};
};
ko.applyBindings(new ViewModel());