Template event attachments being lost when the template is moved

I have two lists that appear adjacent to each other on my page and list items can be dragged from one list into the other, and vice-versa. The list item is a template, within which is a button. The click event for the button is defined using the Template.foobar.events method.

When the page is rendered, if I click this button in a list item, the events fire ok. If, however, I move this list item to the adjacent list, the events no longer fire.

Does anyone know why this is and/or can suggest a way to circumvent this issue?

Without seeing any of your code, it would be hard to diagnose the issue. If you are handling the click event within your list item template, there should be no reason why the event doesn’t fire inside the template regardless of where you ‘move’ it.

But first things first, let’s see some code.

ok, the main code parts are is below. Other code not supplied is simply applying the jquery.sortable to the lists, which allows the items to be moved between the lists:

List item template event:

Template.listItemTpl.events({
    'click .my-button': function(e,t){
        console.log("clicked!");
    }
});

List item template:

<template name="listItemTpl">
    <div id="{{_id}}">
        <button class="my-button">{{item_title}}</button>
    </div>
</template>

List templates:

<template name="listTpl_1">
    <div class="my-list-1">
    </div>
</template>

<template name="listTpl_2">
    <div class="my-list-2">
    </div>
</template>

The items are inserted into list 1 using this function:

renderListItems = function () {
    var itemsColl = getItemsColl();
    var numItems = itemsColl.count();
    if ( numItems > 0 ){
        var parentNode = $(".my-list-1")[0];
        itemsColl.forEach(function (item) {
                Blaze.renderWithData(Template.listItemTpl, {
                    _id: item._id,
                    item_title: item.item_title
                }, parentNode);
        });
    }
};

At this stage clicking the button in list one fires the button event. If I drag an item into list2, the click events no longer fire.

I don’t know why you need the renderListItems function. Can you do the following:

// list1/2 are client side collections
{{#each list1}}
  {{> listItemTpl}}

{{#each list2}}
  {{> listItemTpl}}

//js
Template.helper({
list1: function () {
    return db.list1.find();
}
// same for list2
});

Then when you move an item, get the id of the item, splice from former list, push into latter list.
The helpers for list1/2 will deal with updating the list for you.

Disclaimer: I could be totally wrong as I’m not familiar with your implementation at all.

Agree that your suggestion would work for a simple situation, but my implemantation requires finer control of UI rendering, hence why I use the blaze methods. So if we can asusme that i cannot use the auto-render methos you suggested is there any reason why the click events fail once the item is moved?

Without looking into how Blaze handles DOM event bubbling, it looks like there is an interaction between Blaze and moving DOM elements with jQuery. I’m not too sure what you might do to resolve this within the normal way of event handling in Meteor, but have you looked at themeteorites:blaze-magic-events which uses more traditional binding and may work better with your use case.

I think you are right about the event bubbling conflict when moving items with jquery. I ended up calling the method in the ‘rendered’ function for the list item instead.