I've done some tinkering about with Knockout in search for a better solution on how to bind select lists (dropdowns). I came up with a extender in combination with a binding.
Extender:
ko.extenders.selectList = function (target, params) {
var result = ko.computed({
read: target,
write: function (newValue) {
if (newValue) {
target(newValue);
} else {
target(undefined);
}
}
});
//add some sub-observables
result.options = $.map(params.options, function (v, k) { return { val: k, txt: v }; });
result.caption = params.caption;
function getInitialEnableValue(){
if(params.hasOwnProperty('enable')){
if($.isFunction(params.enable)){
return params.enable();
}
return params.enable;
}
return true;
}
var isEnabled = ko.observable(getInitialEnableValue());
result.enable = ko.computed({
read: function(){
return isEnabled();
},
write: function(newValue){
if(!newValue) result(undefined);
isEnabled(newValue);
}
});
if(isEnabled() && result.options.length === 1){
result(result.options[0].val);
}
//return the new observable
return result;
};
Binding:
var selectListHTML = "<select data-bind=\"value: {0}, options: {0}.options, optionsCaption: {0}.caption, optionsText: 'txt', optionsValue: 'val', enable: {0}.enable\"></select>";
ko.bindingHandlers.selectList = {
init: function(element, vA, aBA,vm,bc){
$(element).html(selectListHTML.replace(/\{0\}/g,vA()));
}
};
Example fiddle
Are there any pitfalls I'm missing? Does this look like good code? Any comments welcome, thanks in advance!