Reliable way to attach unsupported events to items in {{#each}}


#1

I have a library that adds right click menus to items as they are rendered. My current code looks like this:

{{#each}}
    {{> item}}
{{/each}}
Template.item.onRendered(function() {
    context.attach($(this.find('.item')), menu);
});

The problem is, when the #each loop changes from 3 items to 1 item (through application-specific code), the onDestroyed only runs twice (for the two items that disappear so that I can unbind the context menus) and the onRendered function is not rerun for the new item and its context. This tells me that Meteor is changing the current item to the new context and not calling the onRendered function again for that item, while it is correctly destroying the other two items that exist.

This brings me to my question: how can I reliably run a function after the DOM is ready for each context change? If the onRendered function is not being rerun for each item when it changes, is there another function I can use? Any help would be appreciated.


#2

Instead of onRendered, could you create a helper on the .item to add the menu?

I’m not sure if that would make a difference or not, just an idea. :smile:


#3

That works, but it feels hacky. Here’s my functioning code:

<body>
{{#each}}
    {{> item}}
{{/each}}
</body>

<template name="item">
    <div class="item">Test</div>
    {{attachContext}}
</template>
Template.item.helpers({
    attachContext: function() {
        var instance = Template.instance();
        Meteor.defer(function() {
            context.attach($(instance.find('.item')), menu);
        });
    }
});

Anybody have any less hacky feeling suggestions?


#4

As long as you are using Meteor.defer, you should be able to use the onRendered callback instead of the template helper.


#5

Instead of Meteor.defer() you can use Tracker.afterflush()
See example [here] (http://docs.meteor.com/#/full/Blaze-TemplateInstance-subscribe).