Zach Smith
Zach Smith

Reputation: 8971

Meteor: How to make Bootstrap Select reactive?

When using Bootstrap multiselect, I find that the multiselect jquery always fires a little bit too early - before the template has finished pulling data from the helpers, and as a result the select boxes are often empty (I'd say about 60% of the time).

Clearly Template.usersLayout.rendered() is not the right place to call functions that rely on data to have been rendered. What is a better way to do this?

Alternatively, I guess making the bootstrap-select javascript 'reactive would be 1st prize. How can I do this?

code is below

==========

I'm using a helper (#each) to create a select box where each option is it's own data context.

<template name="usersLayout">
    <form>
        <!-- Multiselect for instruments -->
        <div class="form-group">
            <label for="playerInstruments">Player instruments</label>
            <div class="controls text-left">
                <select id="playerInstruments" multiple="multiple" class="selectFilter" name="playerInstruments">
                    {{#each instruments}}
                    <option value="{{name}}">{{name}}</option>
                    {{/each}}
                </select>
            </div>
        </div>
    </form>
</template>

The helper is defined as follows:

Template.usersLayout.helpers({

    /* Database retrievals */

    // Returns all Instruments from Mongo
    instruments: function() {
        return Instruments.find();
    }

})

The twitter bootstrap code is all something like the following:

Template.usersLayout.rendered = function () {

    $('#playerInstruments').multiselect({
        disableIfEmpty: true,
        onChange: function(option, checked) {
            // Set the session as the checked valuess
            var tempSessionArr = $("#playerInstruments").val();
            // Add or delete from Session
            Session.set('playerInstruments', tempSessionArr);
        },
    });
}

Upvotes: 2

Views: 767

Answers (2)

Thai Tran
Thai Tran

Reputation: 9935

The problem is your template does not wait for the data before it start to render, Since data only appears on page after template already rendered, select box is empty. I know that this is your first app and you did not remove the autopublish package, but it is a best practice to follow the full tutorial from Flow Router

First of all, read this. Then, change your router to have the subcriptions options. After that, check if the subscriptions are ready through this (the subsReady() should be inside the rendered function) and then, in the callback of the subsReady(), init the selectbox

Upvotes: 1

Michel Floyd
Michel Floyd

Reputation: 20236

You want to use template events to catch the change event instead of setting up a jQuery hook.

Template.usersLayout.events({
  '#playerInstruments change': function(ev){
    var tempSessionArr = $("#playerInstruments").val();
    Session.set('playerInstruments', tempSessionArr);
  },
});

Then keep your multiselect setup in the onRendered handler:

Template.usersLayout.rendered = function () {
  $('#playerInstruments').multiselect({ disableIfEmpty: true });
};

If this still doesn't work try wrapping the latter with defer:

Template.usersLayout.rendered = function () {
  Meteor.defer(function(){
    $('#playerInstruments').multiselect({ disableIfEmpty: true });
  });
};

Upvotes: 0

Related Questions