Tuesday, June 14, 2016

Knockout Placeholder Select Binding

So, for whatever reason, the select tag does not support the placeholder attribute. If it did, I'm assuming that's what the Knockout binding for optionsCaption would end up setting. I tried a few approaches to get a placeholder effect from the select box and have a decent working example. Of course, as is true with most coding questions, I started with a quick search of stack overflow. I took the example that worked the best for my scenario and turned it into a knockout binding.
At first, I thought I should extend the existing select binding, however, I soon realized there is no select binding; it just uses value, options, optionsText, ... to accomplish its task. So, I looked into adjusting the optionsCaption binding, and saw that it is just part of the options binding and I followed suit.

ko.bindingHandlers.placeHolderSelect = {
    after: ['options', 'value', 'optionsCaption'],
    init: function (elem, value, allBindings, viewModel, bindingContext) {
        var options = ko.utils.unwrapObservable(value());

        if (allBindings['has']('optionsCaption')) {
            var caption = $(elem).find('option[value=""]');

            if (options === 'required') {
                caption.prop('hidden', 'hidden');
                caption.prop('disabled', 'disabled');
            }

            var emptyClass = 'empty';
            $(elem).change(function() {
                if (!$(elem).val()) {
                    $(elem).addClass(emptyClass);
                } else {
                    $(elem).removeClass(emptyClass);
                }
            });
            $(elem).change();
        }
    }
}

To use this binding, simply add placeHolderSelect and set the value to either 'required' if the selection should not allow the caption to be re-selected or any other value if the caption should allow re-selection.

    <!-- Cannot re-select caption -->
    <select data-bind="options: myOptions, optionsCaption: 'Caption Text', placeHolderSelect: 'required'"></select>

    <!-- Can re-select caption -->
    <select data-bind="options: myOptions, optionsCaption: 'Caption Text', placeHolderSelect: false"></select>
Enjoy!

No comments:

Post a Comment