3

I'm trying to do some logic after user completes a selection and moves away from a bootstrap multi-select dropdown.

I tried hooking into the blur event:

      <select id="select1" multiple="multiple" class="form-control" data-bind="options: availableValues, selectedOptions: selectedValues, multiselect: {
    includeSelectAllOption: true
  }, event: { blur: $root.onBlur}">
      </select>  

Defining a onBlur function in my viewModel:

onBlur: function(){
    alert('OnBlur');
}

But it never kicks-in. I even tried setting the event binding directly without the $root.onBlur, just blur: onBlur but didn't work.

Here is a sample JS fiddle:

https://jsfiddle.net/gtzatrL2/

Am I missing something? or is the blur event not applicable to bootstrap multi-selects?

The reason I want to hook into blur is because I have some backend logic to do through Ajax after ALL items have been selected. If I subscribe to my observableArray changes it will trigger my backend call for each item added which is not what I want.

Adolfo Perez
  • 2,834
  • 4
  • 41
  • 61
  • 1
    Bootstrap is actually hiding the original select element and showing a div in its place, so the blur on the select never gets hit. If you want to use bootstrap controls you'll probably need a custom binding to attach the event to the element bootstrap creates instead of the original select. – Jason Spake Mar 08 '17 at 16:07
  • Actually I see you're already doing exactly that by using the bootstrap-multiselect project at https://github.com/davidstutz/bootstrap-multiselect. Unfortunately his binding handler doesn't seem to support Blur. You might petition him to add support or you could copy the handler out of that js file and try modifying it yourself to add blur event support. – Jason Spake Mar 08 '17 at 16:32

4 Answers4

2

Bootstrap is actually hiding the original select element and showing a div in its place, so the blur on the select never gets hit because it isn't being focused in the first place.

I think because the bootstrap controls are using divs it might be impossible to support blur at all because divs aren't normally focusable. There are a couple of workarounds but it might not work in this particular case. See How to blur the div element?

One option instead - you could rate-limit your observableArray so that the subscription doesn't fire immediately every time an option is selected. This will also reduce the backend calls, but it does not guarantee it won't fire before the user is finished.

http://knockoutjs.com/documentation/rateLimit-observable.html

this.selectedValues = ko.observableArray().extend({ rateLimit: { timeout: 500, method: "notifyWhenChangesStop" } });

this.selectedValues.subscribe(function() {
    alert("BLUR: " + this.selectedValues().length + " elements selected");
});
Community
  • 1
  • 1
Jason Spake
  • 4,293
  • 2
  • 14
  • 22
0

Here's a working example -- when the user 'tabs' away to the second input the blur event callback displays how many elements were selected

var ViewModel = function() {
    this.availableValues = ko.observableArray(["Option A", "Option B", "Option C"]);
    this.selectedValues = ko.observableArray();

    this.onBlur = function() {
        alert("BLUR: " + this.selectedValues().length + " elements selected");
    }
};

ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<select id="select1" multiple="multiple" class="form-control" data-bind="options: availableValues, selectedOptions: selectedValues, multiselect: { includeSelectAllOption: true },event: { blur: $root.onBlur}">

<input type="text">
Rafael Companhoni
  • 1,780
  • 1
  • 15
  • 31
0

fyi here's a response from developers github page

https://github.com/davidstutz/bootstrap-multiselect/issues/1020

basically say's that you should call onDropdownHide function wich trigger a kind of "blur" for multiselect plugin

jfernandez_04
  • 152
  • 2
  • 10
0

Bootstrap-select exposes a few events for hooking into select functionality developer.snapappointments.com

So one could refer to hide.bs.select or hidden.bs.select. You could then access the selected values directly from the event parameter or if you have an Knockout observableArray attached to i.e. selectedOptions; like so:

$(document).ready(function () {
     $('#select1').on('hide.bs.select', (e) => {
        console.log({ obs: self.selectedValues(), event: $(e.currentTarget).selectpicker('val') });
    });
});
chri3g91
  • 1,196
  • 14
  • 16