2013-07-18 16 views
7

Próbuję zaimplementować animację, w której element animowany jest po lewej stronie po wybraniu. Poniższy kod działa. Ale tylko około 80% czasu.Meteor Animacja

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(); 
    } 
}); 

Szablony

<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; } 

Próbowałem też owinąć kod do Meteor.defer(), aby upewnić się, że naprawdę wszystko jest gotowe zrobić animację .

Template.myItem.rendered = function(){ 
    Meteor.defer(function() { 
    if(Session.get("selected_item") === this.data._id){ 
     $(this.firstNode).addClass("selected"); 
    } else { 
     $(this.firstNode).removeClass("selected"); 
    } 
    }); 
}; 

jednak, że wyniki w tego rodzaju błędu:

Exception from defer callback: TypeError {} 

Byłoby wspaniale zobaczyć jakieś pomysły, jak uczynić pracę animację za każdym razem.

UPDATE

Krab dostał właściwą odpowiedź. Wyjątek pochodzi z odwołania this. Chcę dodać trochę szczegółów. Więc tutaj są dwie wersje robocze na jak zrobić animację:

z 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" 
    }); 
    } 
}; 

(Nie rzeczywiście trzeba blok innego tutaj, bo meteor usunie klasę selected jeśli rysuje element.)

lub $().animate()

Template.myItem.rendered = function(){ 
    if(Session.get("selected_item") === this.data._id){ 
    $(this.firstNode).animate({ 
     left: "-20px" 
    }, 300); 
    } 
}; 

Jeśli stosowanie metody jQuery trzeba usunąć kod CSS.

.myItem { transition: all 200ms 0ms ease-in; } 
.selected { left: -20px; } 

+0

Więc renderowane oddzwonienia jest wywoływana, gdy coś jest renderowane, więc dlaczego powinno być wywołane, gdy coś jest wybrane? Powinniśmy uzyskać więcej kodu. – Krab

+0

Wyrenderowane wywołanie zwrotne wywoływane jest na każdym 'Session.set (" selected_item ", id);'. Dodałem kod, aby ogólny kontekst był wyraźniejszy. –

Odpowiedz

3

spróbować, bo this wskaźnik w odroczyć zwrotnego nie jest taka sama jak wtedy, gdy kod jest wykonywany bezpośrednio w wytopione zwrotnego

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"); 
    } 
    }); 
}; 
+0

Dzięki! Całkowicie przeoczyłem funkcję "tego" w funkcji odroczenia. Po wymianie "tego" wszystko działa dobrze. –