简体   繁体   中英

Knockout select dropdown disable item

Currently I'm only able to enable/disable the entire drop down using the enable binding in knockout. When Enable = false, the whole drop down is no longer clickable, and user cannot see the other possible values in the drop down.

<select data-bind="options: OptionsList, optionsText: 'Key', optionsValue: 'Value', value: FieldValue, enable: Enable"></select>

what got rendered is this:

<select disabled=""></select>

What I'm hoping to do is render something like this

<select> 
<option disabled="disabled" value='1'>One </option> 
<option selected="select"   value='2'>Two </option> 
<option disabled="disabled" value='3'>Three </option>   
</select>

This way I can still see my options but they are all disabled so the user can't change them.

I have looked at the optionsAfterRender in knockout, but I no longer have access to the selected value. the item passed in is just the key and value of the select item, not the observable.

Any help would be much appreciated. Thanks

You could choose to build your option elements using foreach like:

<select data-bind="value: selected, foreach: options">
    <option data-bind="attr: { disabled: !enabled(), value: value }, text: name"></option>
</select>

Sample: http://jsfiddle.net/rniemeyer/4PuxQ/

Otherwise, here is a sample of an optionsBind binding from Michael Best that would let you bind the option without using a foreach (uses optionsAfterRender functionality):

<select data-bind="value: selected, options: options, optionsText: 'name', optionsValue: 'value', optionsBind: 'attr: { disabled: !enabled() }`"></select>'

Sample: http://jsfiddle.net/rniemeyer/KxY44/

You need to use the optionsAfterRender to apply disabled to the options. It's discussed in the documentation: http://knockoutjs.com/documentation/options-binding.html

<select data-bind="options: OptionsList, optionsText: 'Key', optionsValue: 'Value', value: FieldValue, optionsAfterRender: setOptionDisable"></select>

self.setOptionDisable = function(option, item) {
    ko.applyBindingsToNode(option, {disable: item.disable}, item);
}

Here is a demo of it working: http://jsfiddle.net/vkFUC/

You can use optionsAfterRender for disabling options. You need to provide one more observable property to object for enabling or disabling the option.

Code:-

  //Optionlist will look like this 
  OptionsList: ko.observableArray([{
    Key: 1,
    Value: "Jack",
    disable: ko.observable(false)
  }, {
    Key: 2,
    Value: "Jhon",
    disable: ko.observable(false)
   }]),

    //Function will be used in optionsAfterRender 
    setOptionDisable: function (option, item) {
      ko.applyBindingsToNode(option, {
        disable: item.disable
      }, item);
    }

Fiddle Demo

For version 3.5.0 , if you want to continue to use mbest solution (which I personally find very useful and elegant), just replace the ko.contextFor with the call to this proposed workaround from chrisknoll:

function contextForNodeOrNearestParent(node) {
    // Proposed fix for 3.5.0 ko.contextFor   https://github.com/knockout/knockout/pull/2447/files
    var context = ko.contextFor(node);
    if (!context && node.parentNode) {
        return contextForNodeOrNearestParent(node.parentNode);
    }
    return context;
}

The original custom bindingHandler from mbest would be then modified like this:

ko.bindingHandlers.optionsBind = {
    preprocess: function (value, key, addBinding) {
        addBinding('optionsAfterRender', 'function(option, item) { ko.bindingHandlers.optionsBind.applyBindings(option, item, ' + value + ') }');
    },
    applyBindings: function (option, item, bindings) {
        if (item !== undefined) {
            option.setAttribute('data-bind', bindings);
            //ko.applyBindings(ko.contextFor(option).createChildContext(item), option);
            ko.applyBindings(contextForNodeOrNearestParent(option).createChildContext(item), option);
        }
    }
};

This is working for my project like a charm. And I'm posting this here, in case it can save someone's time, and for future personal reference.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM