skip to Main Content

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);
        },
    });
}

2

Answers


  1. 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 });
      });
    };
    
    Login or Signup to reply.
  2. 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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search