var Lab = function(name, id, options, labsInUse) {
this.name = name;
this.id = id;
this.options = options;
this.selectedOptions = ko.observableArray([]);
this.disabled = ko.pureComputed(function() {
return labsInUse().some(function(thatId) {
return thatId === id;
});
});
};
Lab.fromData = function(d, idsInUse) {
return new Lab(d.lab_name, d.id, d.lab_options.split(","), idsInUse);
}
var Row = function(labs) {
this.labs = labs;
this.selectedLab = ko.observable(labs.find(function(l) {
return !l.disabled();
})
);
this.setOptionDisable = function(option, item) {
ko.applyBindingsToNode(option, { disable: item.disabled }, item);
}
};
var App = function(courseData, initialSelection) {
this.rows = ko.observableArray([]);
// Every lab can only be added once
var labIdsInUse = ko.pureComputed(function() {
return this.rows().map(function(r) {
return r.selectedLab() && r.selectedLab().id;
});
}, this);
var labs = courseData.map(function(d) {
return Lab.fromData(d, labIdsInUse)
});
// Display a report of selections
this.selection = ko.pureComputed(function() {
return this.rows()
.map(function(r) {
var lab = r.selectedLab();
return lab.name + ", with subjects: " + lab.selectedOptions().join(", ");
});
}, this);
this.canAdd = ko.pureComputed(function() {
return labs.length > labIdsInUse().length;
}, this);
this.addRow = function() {
this.rows.push(new Row(labs));
}.bind(this);
this.removeRow = function(row) {
this.rows.remove(row);
}.bind(this);
// Set initial selection
Object.keys(initialSelection)
.map(function(labName) {
var row = new Row(labs);
var labToSelect = labs.find(function(lab) {
return lab.name === labName;
});
// Set options
labToSelect.selectedOptions(
initialSelection[labName]
);
// Add lab to row
row.selectedLab(labToSelect);
// Add row to app
this.rows.push(row);
}.bind(this));
};
ko.applyBindings(
new App(
getCourseData(),
{"Math": ["Calculus", "Algebra"], "English": ["Language"]}
)
);
function getCourseData(){return[{id:"1003",lab_name:"Math",lab_index:"1",lab_options:"Calculus,Algebra,Geometry"},{id:"1004",lab_name:"English",lab_index:"2",lab_options:"Language,Literature,History"},{id:"1005",lab_name:"History",lab_index:"3",lab_options:"Ancient,Modern"}]}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div data-bind="foreach: rows">
<div>
<select data-bind="options: labs, optionsText: 'name', value: selectedLab, optionsAfterRender: setOptionDisable"></select>
<!-- ko with: selectedLab -->
<select data-bind="options: options, selectedOptions: selectedOptions" multiple></select>
<!-- /ko -->
<button data-bind="click: $parent.removeRow">delete</button>
</div>
</div>
<button data-bind="click: addRow, enable: canAdd">add lab</button>
<h3>Selection:</h3>
<ul data-bind="foreach: selection">
<li data-bind="text: $data"></li>
</ul>