Reputation: 5296
I've created a multiple, cascading selects with Knockout, using code inspired by the accepted answer in this question (jsFiddle - code at bottom of post too).
It works great, however I'd like to disable the child selects when they are unavailable, rather than hide them completely.
Is there a simple option for this?
The hide behaviour seems to be driven by the 'with' binding, but this seems integral to how the arrays are linked.
var mainViewModel = null;
var mainViewModelData = {
"RequestName": "test Name",
"BusinessLines": [{
"Id": 1,
"Title": "Retail",
"Clusters": [{
"Id": 1,
"Title": "Corporate si Trezorerie"},
{
"Id": 2,
"Title": "Good Bee"},
{
"Id": 3,
"Title": "Leasing"}]},
{
"Id": 2,
"Title": "Corporate",
"Clusters": [{
"Id": 1,
"Title": "REM"},
{
"Id": 2,
"Title": "BCR Procesare"},
{
"Id": 3,
"Title": "Erste Asset Management"}]}],
"SelectedBusinessLine": null,
"SelectedCluster": null,
"RequirementHighLevelDescription": null,
"Revenues": 0,
"Savings": 0,
"PreventedLosses": 0
};
mainViewModel = ko.mapping.fromJS(mainViewModelData);
ko.applyBindings(mainViewModel);
<div>
<table>
<tr>
<td>
Business Line
</td>
<td>
<select data-bind="options: BusinessLines, optionsText: 'Title', value: SelectedBusinessLine,
optionsCaption: 'Select Business Line..'">
</select>
</td>
</tr>
<tr data-bind="with: SelectedBusinessLine">
<td>
Cluster
</td>
<td> <select data-bind="options: Clusters, optionsText: 'Title', value: $root.SelectedCluster, optionsCaption: 'Select Cluster..'">
</select>
</td>
</tr>
</table>
</div>
Upvotes: 0
Views: 903
Reputation: 3907
It's not so trivial but possible...
First you'd create the computed observable that will merge all the clusters of every BusinessLine with parent
property that will keep cluster's parent BusinessLine object:
mainViewModel.AllClusters = ko.computed(function(){
var result = [];
ko.utils.arrayForEach(this.BusinessLines(), function(line){
ko.utils.arrayForEach(line.Clusters(), function(cluster){
result.push({ parent: line, Title: cluster.Title() });
});
});
return result;
}, mainViewModel);
Then it's necessary to create new type of binding enabledOptions, that will set/remove "disabled" attribute for each cluster <option/>
depending on parent
property comparison result:
ko.bindingHandlers.enabledOptions = {
update: function(element, valueAccessor, allBindings) {
var options = element.getElementsByTagName('option'),
parent = ko.utils.unwrapObservable(valueAccessor()),
// delta is neccessary to strip select's caption if it exists
delta = allBindings().optionsCaption ? 1 : 0;
for (var i = delta; i < options.length; i++) {
var cluster = mainViewModel.AllClusters()[i - delta];
cluster.parent == parent
? options[i].removeAttribute('disabled')
: options[i].setAttribute('disabled', 'disabled')
}
}
}
Finally remove with
binding you've mentioned.
As a result you'll get something like this: http://jsfiddle.net/ostgals/x2qMg/28/
Upvotes: 1