Meteor Animation
animation, css, exception, javascript, meteor
Solution
try this, because `this` pointer in defer callback isn't the same as if the code is executed directly in rendered callback
Template.myItem.rendered = function(){
var self = this;
Meteor.defer(function() {
if(Session.get("selected_item") === self.data._id){
$(self.firstNode).addClass("selected");
} else {
$(self.firstNode).removeClass("selected");
}
});
};
Problem
I am trying to implement an animation where an item animates to the left after it gets selected. The following code works. But only about 80% of the time. JS ``` //myItem Template.myItem.rendered = function(){ if(Session.get("selected_item") === this.data._id){ $(this.firstNode).addClass("selected"); } else { $(this.firstNode).removeClass("selected"); } }; Template.myItem.events({ "click .myItem": function(evt, template){ Session.set("selected_item", this._id); } }); //myItemList Template.myItemList.helpers({ items: function(){ return Items.find(); } }); ``` Templates ``` <template name="myItem"> <div class="myItem">{{name}}</div> </template> <template name="myItemList"> {{#each items}} {{> myItem}} {{/each}} </template> ``` CSS ``` .myItem { transition: all 200ms 0ms ease-in; } .selected { left: -20px; } ``` I also tried to wrap the code into a `Meteor.defer()` to make sure that really everything is ready to do the animation. ``` Template.myItem.rendered = function(){ Meteor.defer(function() { if(Session.get("selected_item") === this.data._id){ $(this.firstNode).addClass("selected"); } else { $(this.firstNode).removeClass("selected"); } }); }; ``` But that results in this kind of error: ``` Exception from defer callback: TypeError {} ``` It would be great to see any ideas how to make the animation work every time. UPDATE Krab got the right answer. The exception was coming from the `this` reference. I want to add some details. So here are two working versions on how to do the animation: with `Meteor.defer()` ``` Template.myItem.rendered = function(){ var instance = this; if(Session.get("selected_item") === this.data._id){ Meteor.defer(function() { $(instance.firstNode).addClass("selected"); //use "instance" instead of "this" }); } }; ``` (We don't actually need the else block here because meteor will remove the `selected` class if it redraws the item.) or with `$().animate()` ``` Template.myItem.rendered = function(){ if(Session.get("selected_item") === this.data._id){ $(this.firstNode).animate({ left: "-20px" }, 300); } }; ``` If you use the jQuery approach you need to remove the CSS code. ``` .myItem { transition: all 200ms 0ms ease-in; } .selected { left: -20px; } ```