javascriptknockout.jscustom-bindingbootstrap-multiselect

Knockout custom binding for bootstrap select not updating viewmodel "selectedCategories/selectedCategory"


I am creating a knockout js custom binding that will allow me to use data-binding with bootstrap multiselect. I need it to work for single <select>'s and also multiselects <select multiple="true">. I am doing it in this jsfiddle

I have got it so that both single and multiselects can show the dropdown options and as new categories are added with the button, they show on the multiselect dropdown. I also want to update the viewmodels selectedItems which are _selectedCategory for the single <select> and '_selectedCategories' for the multiselect.

I have added some buttons into the jsfiddle to test the bootstrap multiselect elements.

How can the viewmodels _selectedCategories and _selectedCategory be updated upon selecting the DOM elements from the dropdowns?

The code is in the jsfiddle


Solution

  • I'm not sure I can get you to the point of making it work, but some pointers:

    1. DOM manipulation belongs in the binding handler. In particular, the initialization: $(this).multiselect({ goes in the init.
    2. The parameter object you pass to that initialization is what should be the bound variable for your multiselect binding. (I have no idea what _categoryID is for.) It will be what causes the update to fire. It will be what valueAccessor() returns.
    3. Although optionsText and optionsValue should have simple string arguments, value's argument should be an unquoted observable name. This is one key issue in the question you're asking.
    4. Only wrap (directly call the ko.bindingHandlers entry for) handlers that you aren't binding separately, and only when you need their binding to be part of what you're doing. You may need to wrap options, optionsText, and optionsValue instead of including them in the data-bind. But one or the other.

    Update I've updated your fiddle to handle the multiselect case. I didn't find that the selectedOptions binding handler was working for me, so I had to put this in the init. This breaks the single-select case; need to special-case it.

      $(element).change(function (e) {
        var selectedOptions = ko.utils.arrayFilter(Array.from(e.target.options), function (opt) {
          return opt.selected;
        });
        var selectedValues = ko.utils.arrayMap(selectedOptions, function (opt) {
          return opt.value;
        });
        valueAccessor()(selectedValues);
      });