[solved] Run code on DOM render\re-render

HTML

<template name='sometpl'>
  <select>
    <option>day</option>
    <option>night</option>
  </select>
  <br>
  <p>Now is: </p>
  {{#if day}}
    <span class='time' data-content="I'm awake!">day</span>
  {{/if}}
  {{#if night}}
    <span class='time' data-content="I'm asleep">night</span>
  {{/if}}
</template>

coffee

Template.tpl.helpers
  day:-> if $('select').val()=='day' then true
  night:-> if $('select').val()=='night' then true
    
Template.tpl.onRendered ->
      $('.ui.popup').popup()

This code $('.ui.popup').popup() initializes popups on respective elements (semantic-ui).The problem is that it’s ran only once on tpl render thus affecting only this node: <div class='ui popup' data-popup='I'm awake!'>day</div>.
When I choose night this code $('.ui.popup').popup() is not run leaving newly rendered node <div class='ui popup' data-popup='I'm asleep'>night</div> without popup.
Moreover, when I select day back again - it doesn’t have popup this time! As it has invoked rendering of entirely new ‘day’ div, and not the old one.
What can be done here?

You need to:

  1. catch the “change” event of the select,
  2. store the value in a ReactiveVar or a Sesion variable
  3. return this value from within your helpers

I don’t see how this helps. Maybe an example?

Pardon my coffeescript if it’s wrong:

Template.tpl.onCreated ->
  @daySelected = new ReactiveVar

Template.tpl.helpers
  day: -> Template.instance().daySelected.get() is 'day'
  night: -> Template.instance().daySelected.get() is 'night'

Template.tpl.events
  'change select': (e) ->
    @daySelected.set e.target.value

Make sure you’ve installed the reactive-var package.

1 Like

Thanks for your solution, but it doesn’t seem to work:
http://meteorpad.com/pad/XWAYxJyeo5qTck39H/dom%20re-render

Weird, it works here (after translating to javascript).

Template.tpl.helpers({
  day: function(){ 
    var day = Template.instance().daySelected.get();
    return day == 'day';
  },
  night: function() {
    var day = Template.instance().daySelected.get();
    return day == 'night';
  },
});

missed () for get Template.instance().daySelected.get()

In my pad everything’s been corrected and the helpers are working fine: you can see that initially if you hover over day, the popup is there and after you change select, ‘day’ changes to ‘night’ as expected.
Thing is - $('.ui.popup').popup() isn’t getting called again on the newly rendered span element!

I guess, I should use this.autorun inside Template.tpl.onRendered somehow… but can’t figure out how exactly :grin:

this works for me …

Template.tpl.onRendered(function(){
  this.autorun(function(){
    var day = Template.instance().daySelected.get(); // reactivity
    Tracker.afterFlush(function(){ // wait for rendering to be done
	    $('.time').popup().each(function(){console.log(this)});
    });
  });
});
2 Likes

Ah, so that’s the code to use to do something AFTER stuff has finished rendering. I was just trying to confirm this.

Whoa! Thanks, mate! You’ve just saved me lots of repeating lines of code if I went for wrapping each day\night component (of which I have dozens) into a separate template - phew…
Now I just need to sort out how this Tracker stuff works…)
I’ve updated my pad for those facing same issues.

@jamgold, kudos once again :smile:
@lai, thank you too, man :thumbsup: