user2602152
user2602152

Reputation: 797

Dynamic data collection with Select2 and Meteor.js?

I have set up a collection as the source for my data in a Select2 multiple select as so:

<template name="mySubjectsSelector">
    <div>
        <select id="mySubjects" data-placeholder="Choose your subjects" multiple>
            {{#each subjects}}
                <option>{{this.name}}</option>
            {{/each}}
        </select>
    </div>
</template>

And the .js:

Template.mySubjectsSelector.subjects = function () {
    console.log("Fetching subjects...");
    return Subjects.find({}).fetch();
};

Template.mySubjectsSelector.rendered = function () {
    console.log("mySubjectsSelector is rendered!");
    $('#mySubjects')
        .select2({
            width: "300px"
        });
};

Whenever the Subjects collection is updated, it reactively re-renders the template, and that is fine, that's how I want it to behave. The unwanted behaviour, is that it will select the first option in the list when it is re-rendered, on ALL clients!

How can I avoid the selecting of the first item when it reloads/rerenders?

Upvotes: 3

Views: 1995

Answers (2)

emgee
emgee

Reputation: 1234

What I did is create a blank first option.

<template name="mySubjectsSelector">
  <div>
    <select id="mySubjects" data-placeholder="Choose your subjects" multiple>
      <option></option>
      {{#each subjects}}
        <option>{{this.name}}</option>
      {{/each}}
    </select>
  </div>
</template>

There's probably a smarter way of doing this, but it worked for me.

EDIT:

The more involved, Meteor-specific technique I have used to preserve values of the Select2 controls, by storing the values in a Session variable. Something like this:

Template.template.rendered = function () {

// assumes 1) all Select2 controls are originally <select> tags
//     and 2) all Select tags have ids assigned

  $('select').each(function (i) { 
    if (Session.get('preserve-' + this.id)) {
      $(this).val(Session.get('preserve-' + this.id));
    }
  });

  $('.select2').select2({ /* select2 code here */ })
  .on('change', function (e) {
    if (e.val !== "") {
      Session.set("preserve-" + e.target.id, e.val")
    }
  });

};

However: I may have not understood the question exactly. If you are only asking how using Select2 to allow unselected answers, try a placeholder and allowclear. From the docs:

$("#e2").select2({
  placeholder: "Select a State",
  allowClear: true
});

Upvotes: 2

Tobias
Tobias

Reputation: 4074

Have you tried specifying a rule to preserve the <select> and <option> elements?

  Template.mySubjectsSelector.preserve({
      'select[id]': function (node) { return node.id; },
      'option': function (node) { return node.id; }
    });

Also see the documentation.

Another problem could be that the <option> elements don't have ids. Also from the documentation:

By default, new Meteor apps automatically include the preserve-inputs package. This preserves all elements of type input, textarea, button, select, and option that have unique id attributes or that have name attributes that are unique within an enclosing element with an id attribute. To turn off this default behavior, simply remove the preserve-inputs package.

Upvotes: 0

Related Questions