Problem with afterflush | Need to init a tooltip after template changes


#1

Hello, I need to show a text when the global helper isModifiable returns true. And I need to initialize the tooltip which comes with this text with a jQuery script
{{#if isModifiable}} <p>SOME TEXTS<a class="tooltipped" data-position="bottom" data-delay="50" data-tooltip="I am tooltip">?</a></p> {{else}} <p>SOME OTHER TEXTS</p> {{/if}}
The problem is that isModifiable is a reactive data source and actually changes AFTER my template is rendered. So I need to call my init script : $('.tooltipped').tooltip() when isModifiable changes.
So as I will not use unelegant solution as setTimeout, that’s for sure, I try to use tracker.autorun to track changes

Tracker.autorun(() => { if (Session.get('charting-modifiable')) { Tracker.afterFlush(() => { $('.tooltipped').tooltip(); }); }});
But afterflush is always called BEFORE template changes. Which is … not the behavior I expected. I can’t figure out why afterFlush is called before DOM changes. I also try to call Tracker.flush() just after changing session variable but still my init script is never triggered when the #if variable changes…


#2

have more code to go on?

Are you calling afterFlush in onRendered?


#3

Hello I tried to cut part from all the file involved here : http://codepaste.net/47d6gr . I hope this is good. To summarize I only want to do a basic stuff : if Session.get(‘charting-modifiable’) is true 1) change the admin template to notify user 2) launch a jQuery script to initialize the tooltip.
Thanks to anyone who could try to help :smiley:


#4

I think the best way to solve this is to make
<p>Vous pouvez modifier le contenu du cours <a class="tooltipped" data-position="bottom" data-delay="50" data-tooltip="I am tooltip">? </a> </p>
its own template with its own onRendered callback


#5

Yes, or I could make it transparent instead of removing from the DOM. Although there is plenty of inelegant solutions I still would like to understand what’s I am missing with afterflush.


#6

What I usually do is to initialize the tooltip in a deferred function called from the helper. So in your case:

Template.name.helpers({
    isModifiable() {
        let isModifiable = ...something...;
        Meteor.defer( () => {
            initializeTooltip();
        }
        return isModifiable;
    }
}

That way you are sure that you always initialize the tooltip when the DOM changes, and after the change is ready.
And you don’t need extra autoruns.


#7

Thanks a lot, it’s the perfect solution, exactly what I first wanted, thanks a lot @jesperwe !
PS : still wondering why afterFlush trigger before DOM modification but my problem is solved in any way


#9

Sorry I was too fast. Still with :
isModifiable() {
const isModifiable = Session.get(‘charting-modifiable’);
Meteor.defer(() => {
$(’.tooltipped’).tooltip({delay: 50});
});
return isModifiable;
}
my tooltip is not init ! :frowning: But still when I use my jQuery script in my console it does work…
EDIT : I really don’t understand what the problem. How could .afterFlush(), .flush() and .defer() just working for anyone but me :s


#10

That’s crazy, I don’t know if one of the meteor’s team is here or anyone who could understand what’s wrong, but I register and afterFlush triggers each time right after the DOM has changed. I’m wondering if I made an huge mistake or if it’s a real bug?


#11

I still need a solution.


#12

If you want to do jquery stuff in blaze you often need to do this in the next render event in order to make it work. You do that like this:

Meteor.setTimeout ->
    $('.tooltip').tooltip()
, 0

#13

Thanks but still nothing is initialized after DOM update, in any way I think it’s the same as Meteor.defer()
PS : as for now I’m obliged to have in many places setTimeout with arbitrary values (more than 0), Meteor was said to love beautiful code but because of Meteor bugs I’ve an horrible dirty code !!