JSFiddle - React, Tailwind, and code Playground
HTML
<select id="jurisdictions-dropdown" multiple="multiple"></select>
CSS
.multiselect-container {
position:absolute;
list-style-type:none;
margin:0;
padding:0
}
.multiselect-container .input-group {
margin:5px
}
.multiselect-container>li {
padding:0
}
.multiselect-container>li>a.multiselect-all label {
font-weight:700
}
.multiselect-container>li.multiselect-group label {
margin:0;
padding:3px 20px 3px 20px;
height:100%;
font-weight:700
}
.multiselect-container>li.multiselect-group-clickable label {
cursor:pointer
}
.multiselect-container>li>a {
padding:0
}
.multiselect-container>li>a>label {
margin:0;
height:100%;
cursor:pointer;
font-weight:400;
padding:3px 20px 3px 40px
}
.multiselect-container>li>a>label.radio, .multiselect-container>li>a>label.checkbox {
margin:0
}
.multiselect-container>li>a>label>input[type=checkbox] {
margin-bottom:5px
}
.btn-group>.btn-group:nth-child(2)>.multiselect.btn {
border-top-left-radius:4px;
border-bottom-left-radius:4px
}
.form-inline .multiselect-container label.checkbox, .form-inline .multiselect-container label.radio {
padding:3px 20px 3px 40px
}
.form-inline .multiselect-container li a label.checkbox input[type=checkbox], .form-inline .multiselect-container li a label.radio input[type=radio] {
margin-left:-20px;
margin-right:0
}
JavaScript
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery', 'knockout'], factory);
} else {
// Browser globals
factory(root.jQuery, root.ko);
}
})(this, function ($, ko) {
"use strict";
if (typeof ko !== 'undefined' && ko.bindingHandlers && !ko.bindingHandlers.multiselect) {
ko.bindingHandlers.multiselect = {
after: ['options', 'value', 'selectedOptions'],
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
var $element = $(element);
var config = ko.toJS(valueAccessor());
$element.multiselect(config);
if (allBindings.has('options')) {
var options = allBindings.get('options');
if (ko.isObservable(options)) {
ko.computed({
read: function () {
options();
setTimeout(function () {
var ms = $element.data('multiselect');
if (ms) ms.updateOriginalOptions(); //Not sure how beneficial this is.
$element.multiselect('rebuild');
}, 1);
},
disposeWhenNodeIsRemoved: element
});
}
}
//value and selectedOptions are two-way, so these will be triggered even by our own actions.
//It needs some way to tell if they are triggered because of us or because of outside change.
//It doesn't loop but it's a waste of processing.
if (allBindings.has('value')) {
var value = allBindings.get('value');
...