21

I want to use Bootstrap Multiselect Dropdown http://davidstutz.github.io/bootstrap-multiselect/ in AngularJS. I hear that it's necessary to move it to Directive. But I think it's quite complicated & don't know what I have to do. If you have experienced, please guide me! Tks.

2

3 Answers 3

16

Here is a directive I use in my project. It works on Chrome and Firefox. You can change the options based on your own need.

angular.module('yourApp') .directive('yourDirective', function () { return { link: function (scope, element, attrs) { element.multiselect({ buttonClass: 'btn', buttonWidth: 'auto', buttonContainer: '<div class="btn-group" />', maxHeight: false, buttonText: function(options) { if (options.length == 0) { return 'None selected <b class="caret"></b>'; } else if (options.length > 3) { return options.length + ' selected <b class="caret"></b>'; } else { var selected = ''; options.each(function() { selected += $(this).text() + ', '; }); return selected.substr(0, selected.length -2) + ' <b class="caret"></b>'; } } }); // Watch for any changes to the length of our select element scope.$watch(function () { return element[0].length; }, function () { element.multiselect('rebuild'); }); // Watch for any changes from outside the directive and refresh scope.$watch(attrs.ngModel, function () { element.multiselect('refresh'); }); } }; }); 

Update two snippets for the directive which working on AngularJS v1.3.15 and bootstrap-multiselect v0.9.6: JavaScript, CoffeeScript

7
  • this works great for me EXCEPT on firefox. When the buttonText function is called after I select something in firefox, the length is always zero, so it doesnt update the text shown. Thoughts?CommentedOct 14, 2013 at 2:24
  • @LukeOllett It works in my project on both Chrome and Firefox. I guess there might be some issues in the HTML file. In select tag, I use ng-options and allow multiple.
    – Ethan Wu
    CommentedOct 15, 2013 at 0:19
  • mine looks like this ... <select ng-if="event.guests.length" class="multiselect" ng-options="guest.id as (guest.name | truncate:40) for guest in event.guests" data-placeholder="No Guests Selected" ng-model="guestSelection" multiple="multiple" table="table" multiselect-table-dropdown> </select>CommentedOct 15, 2013 at 3:27
  • looks like the repo was updated recently with a similar bug fix and my problem has been resolved. thanks for following up and this solution.CommentedOct 15, 2013 at 3:39
  • 1
    @MrMuh Actually, I don't know. I use ui-bootstrap in my project too. But I don't use the drop-down directive with this one together. I think you don't need the drop-down directive to create a drop-down list if you are using Bootstrap Multiselect Dropdown.
    – Ethan Wu
    CommentedJan 31, 2014 at 22:19
14

If you don't need to create code that's very re-usable, it's actually not that complicated. The first step is to create a basic directive and to get the DOM element:

angular.module('yourapp', []) .directive('multiselectDropdown', [function() { return function(scope, element, attributes) { element = $(element[0]); // Get the element as a jQuery element // Below setup the dropdown: element.multiselect({ option1: 123, option2: "abcd", // etc. }) // Below maybe some additional setup } }]); 

Basically, once you are within the directive, it's actually just regular jQuery or JS code.

Then in your HTML code:

<select multiselectDropdown > <option value="1">One</option> <option value="2">One</option> <option value="3">One</option> </select> 

You can also specify additional attributes on the DIV and get the values using the attributes parameter of the directive.

9
  • 7
    Just as an addon this is an excellent model for all jquery plugins you want to migrate to AngularJS. Shouldn't your 'multiselectDropdown' be 'multiselect-dropdown'?CommentedJun 6, 2013 at 6:08
  • 1
    Actually, the latest version of AngularJS supports many way to assign directives in HTML, I think multiselect-dropdown, multiselectdropdown, data-multiselect-dropdown, class="multiselect-dropdown" (and probably more) are all valid. "multiselect-dropdown" might indeed be more proper HTML than "multiselectDropdown".
    – laurent
    CommentedJun 6, 2013 at 7:45
  • @Laurent Sorry, but I haven't really known what to do next :|CommentedJun 6, 2013 at 13:49
  • @OcChuojDau, well for a start, does the code make sense at all? :) If it doesn't, what is it you don't understand?
    – laurent
    CommentedJun 6, 2013 at 14:54
  • @Laurent To me, Directive is being a very difficult & big aspect :| Could you please help me to write the code in more details in this situation? I really appreciate!CommentedJun 6, 2013 at 17:55
0

Here is my take on Ethan Wu's answer. I fixed a couple of bugs and added options that are overridable on the element: <select multi-select includeSelectAllOption="true" enableFiltering="true" enableClickableOptGroups="true" enableCollapsibleOptGroups="true" multiple ng-model="vm.selectedPlants" ng-options="plant.name group by plant.operatingCompanyName for plant in vm.plants"></select>

Gist

// AngularJS: 1.5.8 // bootstrap-multiselect: 0.9.13 angular.module('SocoApp') .directive('multiSelect', function () { return { link: function (scope, element, attrs: any) { var options: any = { onChange: function (optionElement, checked) { if (optionElement != null) { $(optionElement).removeProp('selected'); } if (checked) { $(optionElement).prop('selected', 'selected'); } element.change(); } }; //attrs are lowercased by Angular, but options must match casing of bootstrap-multiselect if (attrs.enablehtml) options.enableHTML = JSON.parse(attrs.enablehtml); //default: false if (attrs.buttonclass) options.buttonClass = attrs.buttonclass; //default: 'btn btn-default' if (attrs.inheritclass) options.inheritClass = JSON.parse(attrs.inheritclass); //default: false if (attrs.buttonwidth) options.buttonWidth = attrs.buttonwidth; //default: 'auto' if (attrs.buttoncontainer) options.buttonContainer = attrs.buttoncontainer; //default: '<div class="btn-group" />' if (attrs.dropright) options.dropRight = JSON.parse(attrs.dropright); //default: false if (attrs.dropup) options.dropUp = JSON.parse(attrs.dropup); //default: false if (attrs.selectedclass) options.selectedClass = attrs.selectedclass; //default: 'active' if (attrs.maxheight) options.maxHeight = attrs.maxheight; //default: false, // Maximum height of the dropdown menu. If maximum height is exceeded a scrollbar will be displayed. if (attrs.includeselectalloption) options.includeSelectAllOption = JSON.parse(attrs.includeselectalloption); //default: false if (attrs.includeselectallifmorethan) options.includeSelectAllIfMoreThan = attrs.includeselectallifmorethan; //default: 0 if (attrs.selectalltext) options.selectAllText = attrs.selectalltext; //default: ' Select all' if (attrs.selectallvalue) options.selectAllValue = attrs.selectallvalue; //default: 'multiselect-all' if (attrs.selectallname) options.selectAllName = JSON.parse(attrs.selectallname); //default: false if (attrs.selectallnumber) options.selectAllNumber = JSON.parse(attrs.selectallnumber); //default: true if (attrs.selectalljustvisible) options.selectAllJustVisible = JSON.parse(attrs.selectalljustvisible); //default: true if (attrs.enablefiltering) options.enableFiltering = JSON.parse(attrs.enablefiltering); //default: false if (attrs.enablecaseinsensitivefiltering) options.enablecaseinsensitivefiltering = JSON.parse(attrs.enableCaseInsensitiveFiltering); //default: false if (attrs.enablefullvaluefiltering) options.enableFullValueFiltering = JSON.parse(attrs.enablefullvaluefiltering); //default: false if (attrs.enableclickableoptgroups) options.enableClickableOptGroups = JSON.parse(attrs.enableclickableoptgroups); //default: false if (attrs.enablecollapsibleoptgroups) options.enableCollapsibleOptGroups = JSON.parse(attrs.enablecollapsibleoptgroups); //default: false if (attrs.filterplaceholder) options.filterPlaceholder = attrs.filterplaceholder; //default: 'Search' if (attrs.filterbehavior) options.filterBehavior = attrs.filterbehavior; //default: 'text', // possible options: 'text', 'value', 'both' if (attrs.includefilterclearbtn) options.includeFilterClearBtn = JSON.parse(attrs.includefilterclearbtn); //default: true if (attrs.preventinputchangeevent) options.preventInputChangeEvent = JSON.parse(attrs.preventinputchangeevent); //default: false if (attrs.nonselectedtext) options.nonSelectedText = attrs.nonselectedtext; //default: 'None selected' if (attrs.nselectedtext) options.nSelectedText = attrs.nselectedtext; //default: 'selected' if (attrs.allselectedtext) options.allSelectedText = attrs.allselectedtext; //default: 'All selected' if (attrs.numberdisplayed) options.numberDisplayed = attrs.numberdisplayed; //default: 3 if (attrs.disableifempty) options.disableIfEmpty = JSON.parse(attrs.disableifempty); //default: false if (attrs.disabledtext) options.disabledText = attrs.disabledtext; //default: '' if (attrs.delimitertext) options.delimiterText = attrs.delimitertext; //default: ', ' element.multiselect(options); // Watch for any changes to the length of our select element scope.$watch(function () { //debugger; return element[0].length; }, function () { scope.$applyAsync(element.multiselect('rebuild')); }); // Watch for any changes from outside the directive and refresh scope.$watch(attrs.ngModel, function () { element.multiselect('refresh'); }); } }; }); 

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.