Tri Nguyen
Tri Nguyen

Reputation: 11098

Meteor on collection change update Template select element

I am using bootstrap-select to help make select elements look better in my Meteor app.

However, I am running into an issue where upon submitting changes to the Meteor Collection, the reactivity pushes out changes back to the templates, thus rewriting the select elements and destroy the original select element, which also take away the bootstrap-select stuff.

I wonder if there's a way for me to prevent this from happening somehow. I tried to listen to the changes and recall selectpicker upon an update but it doesn't work.

Applications.find().observe({
changed: function() {
    console.log('something changed');
            $('.selectpicker').selectpicker();
}
});

I even try to delay things a little bit, also to no avail.

Applications.find().observe({
changed: function() {
    console.log('something changed');
    setTimeout(function(){
        $('.selectpicker').selectpicker();
        console.log('trying to update select picker');
    }, 1000);
}
});

Has anyone run into this problem before and know how to fix it?

EDIT: Here's the template code

<div class="form-group">
    <label for="college" class="control-label">College/ University</label>
    <select class="selectpicker" name="college" placeholder="Select a College/ University">
        {{#each colleges}}
            <option value="{{slug}}">{{name}}</option>
        {{/each}}
    </select>
</div>

Upvotes: 2

Views: 1418

Answers (3)

udondan
udondan

Reputation: 59989

Things changed a bit since this question was asked. With the new Blaze rendering engine the rendered event would only be thrown once. At the time of rendering, the options are not available, resulting in a nice styled but empty select.

The following example takes care of these changes. The trick is to render the selectpicker once on startup and then refresh whenever there's a change to an option. Therefore the <option> has to be moved to it's own template block.

Template:

<template name="whatever">
<div class="form-group">
    <label for="college" class="control-label">College/ University</label>
    <select class="selectpicker" name="college" placeholder="Select a College/ University">
        {{#each colleges}}
            {{> selectOption}}
        {{/each}}
  </select>
</div>
</template>

<template name="selectOption">
    <option value="{{slug}}">{{name}}</option>
</template>

JavaScript:

Template.whatever.rendered = function(){
  $('.selectpicker').selectpicker();
};

var renderTimeout = false;
Template.selectOption.rendered = function(){
  if(renderTimeout !== false) {
    Meteor.clearTimeout(renderTimeout);
  }
  renderTimeout = Meteor.setTimeout(function() {
    $('.selectpicker').selectpicker("refresh");
    renderTimeout = false;
  }, 10)
};

Refreshing is a bit tricky. When you're loading your collection into the select, the event would be thrown for each option. In my case I have hundreds of documents/options. This results in refreshing hundreds of times and the browser hangs for a few seconds. Therefore there is this small timeout, which takes care of refreshing only once for a bulk of changes.

Upvotes: 1

JyrkiH
JyrkiH

Reputation: 11

I had the same issue. Turns out that removing 'preserve-inputs' package from my Meteor app helped. Maybe it's worth trying? Or if you don't want to do that, taking id and/or name attributes away from your select element seems to have same impact.

Upvotes: 1

Peppe L-G
Peppe L-G

Reputation: 8345

In your HTML-template, if you surround your select-element with the constant block helper, the part inside the constant block won't be re-rendered. Maybe that would be a solution?

Upvotes: 1

Related Questions