[SOLVED] Bootstrap-Select options do not update when using Vue bindings with a <select>

Created: 29 Dec 2018

Like this article? Please leave feedback on development.thatoneplace.net!

Problem

I have a webpage that has two dropdowns. The second dropdown's options are dependent on the first's selected value(s). I am using Vue to bind the options and selected values for both <select> elements. I am also using bootstrap-select to provide the user more elegant controls to make their selections.

bootstrap-select wraps and hides the original <select> to use its own set of HTML elements for the nicer experience, and keeps the original <select>'s selected value in sync in the JavaScript DOM. This allows the form to still be submitted without any extra work on your part
... normally ...
But using Vue for binding both the <option>s and the selected value for your <select> and you change the options on the Vue model, Vue will properly update the now-hidden <select>, but the bootstrap-select will not be updated.

As I mentioned before, bootstrap-select syncs the selected value, but it apparently does not sync the options.

Consider the example below:

Video Game Selector Example (BROKEN)

We have a Genre dropdown and a Video Game dropdown. Select different Genres to change the Video Game options. The changed options will appear as JSON under the dropdowns, but you will notice the Video Game dropdown options remain as the old values.

The bootstrap-select dropdowns

Vue data

Selected Genre: {{ selectedGenre }}
{{ gameOptions }}
Selected Video Game ID: '{{ selectedGame }}'

Observations

Play with the Video Game dropdown after changing the Genre. Each time you change Genre, click the Video Game drop down to see that the options remain the same, despite the JSON updating below. When on a different Genre than the default 'Racing', you should notice weirdness including, but not limited to,

Solution

bootstrap-select offers a way to refresh itself, to re-sync the options from the original select. You must call this method explicitly AFTER Vue has performed its update.

We simply add a watch to our Vue model so we can explicitly refresh the video game bootstrap-select, using Vue's $nextTick function to ensure binding updates for gameOptions are completed first.


watch: {
	gameOptions: function(newValues, oldValues){
		this.$nextTick(function(){ $('#video-game-selector').selectpicker('refresh'); });
	}
}
	

Video Game Selector Example (FIXED)

We have a Genre dropdown and a Video Game dropdown. Select different Genres to change the Video Game options. The changed options will appear as JSON under the dropdowns, but you will notice the Video Game dropdown options remain as the old values.

The bootstrap-select dropdowns

Vue data

Selected Genre: {{ selectedGenre }}
{{ gameOptions }}
Selected Video Game ID: '{{ selectedGame }}'

Recommendations for using Vue with bootstrap-select: