What is up with this?


#1

I’ve been working on one of the example todo apps, trying to learn me some stuff about animations with _uihooks (is that bad? It wasn’t in the documentation, but I saw some Gists and other places where people were using it).

Anyway, the problem I’m having has to do with the value of this in the Template.body.onRendered callback.

That works the same way with the body template, right, even though it’s not in part of an actual <template> element?

If it’s not that, then either I"m misunderstanding the API docs or have been staring at this code for way too long.

Everytime it runs, I get a TypeError that says the the .find() method on this (the Template.instance() inside the onRendered callback) is undefined.

Here’s the code I’m using. I cannot see what the problem with it is:

// Animations
Template.body.onRendered = function animateFadeOut() {
	// Why is Chrome saying "this" is undefined?
	console.dir(this);
	
	// When a user clicks a task's .delete button,
	// fade its opacity out before it is removed from the DOM
	this.find('.animated')[0]._uihooks = {
		removeElement: function(node) {
			var animationFinished;
			animationFinished = 'webkitTransitionEnd oTransitionEnd transitionEnd msTransitionEnd transitionend';

			// Adding this class to the element causes the CSS3
			// opacity animation (fade out) to begin
			$(node).addClass('fadeOut');

			// The callback registered here will listen for the 
			// animationFinished callbacks defined above (cross-
			// browser events) and remove the element from the 
			// DOM when they're done.
			$(node).on(animationFinished, function() {
				return $(node).remove();
			});
		}
	};
};

`

Thanks in advance to anyone who can point it out to me.


#2

this.find('.animated')[0] is probably undefined (i.e. no element with class animated was found). So when you’re trying to set the property _uihooks, you’re doing so on an instance of undefined, which will cause an error to be thrown. That’s my guess.

Remember, even if your template is rendered, if there are elements being drawn based on incoming async data (and those elements are the ones that have the animated class) there won’t be any elements in the DOM with that class when onRendered is called.

By the way, shouldn’t it be:

Template.body.onRendered(function() {
   // Code here
});

#3

That way of defining onRendered is deprecated. Use this:

Template.body.onRendered(function () {
  [...]
});

I’m not sure if that’s the issue though (probably not). I’m curious about Template.body, is that a valid template? console.dir(this) as the first statement within the function should return a proper object. That leads me to believe something is wrong with your template.


#4

Ah. Template.body appears to be reserved. Call your template something else.