In Angular 1.x we can use ngAnimate to detect when we are leaving or entering a particular route. Furthermore we are able to apply behaviors to them:
animateApp.animation('.myElement', function(){
return {
enter : function(element, done) {
//Do something on enter
},
leave : function(element, done) {
//Do something on leave
}
};
)};
Resulting in a product like this: http://embed.plnkr.co/uW4v9T/preview
I would like to do something similar with Angular 2.0 and I feel like I'm pretty close...
So here goes, I've created a simple router in the main application component that controls the navigation between the home and about components.
import { bootstrap, bind, Component, provide, View } from 'angular2/angular2';
import {RouteConfig, RouteParams, ROUTER_DIRECTIVES, ROUTER_PROVIDERS, APP_BASE_HREF, ROUTER_BINDINGS} from 'angular2/router'
/////////////////////////////////////////////////////////////////
// Home Component Start
/////////////////////////////////////////////////////////////////
@Component({
selector: 'home-cmp'
})
@View({
template: `
<h2 class="title">Home Page</h2>
`
})
class HomeCmp implements OnActivate, onDeactivate{
onActivate(next: ComponentInstruction, prev: ComponentInstruction) {
console.log("Home Page - initialized");
}
onDeactivate(next: ComponentInstruction, prev: ComponentInstruction) {
console.log("Home Page - destroyed");
}
}
/////////////////////////////////////////////////////////////////
// Home Component End
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
// About Component Start
/////////////////////////////////////////////////////////////////
@Component({
selector: 'about-cmp'
})
@View({
template: `
<h2 class="title">About Page</h2>
`
})
class AboutCmp implements OnActivate, onDeactivate {
onActivate(next: ComponentInstruction, prev: ComponentInstruction) {
console.log("About Page - initialized");
}
onDeactivate(next: ComponentInstruction, prev: ComponentInstruction) {
console.log("About Page - destroyed");
}
}
/////////////////////////////////////////////////////////////////
// About Component End
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
// Main Application Componenent Start
/////////////////////////////////////////////////////////////////
@Component({
selector: 'my-app'
})
@View({
template: `
<div>
<h1>Hello {{message}}!</h1>
<a [router-link]="['./HomeCmp']">home</a>
<a [router-link]="['./AboutCmp']">about</a>
<hr>
<router-outlet></router-outlet>
</div>
`,
directives: [ROUTER_DIRECTIVES]
})
@RouteConfig([
{path: '/', component: HomeCmp, as: 'HomeCmp'},
{path: '/about', component: AboutCmp, as: 'AboutCmp'}
])
export class App {
}
/////////////////////////////////////////////////////////////////
// Main Application Componenent End
/////////////////////////////////////////////////////////////////
bootstrap(App, [
ROUTER_BINDINGS,
ROUTER_PROVIDERS,
ROUTER_DIRECTIVES,
provide(APP_BASE_HREF, {useValue: '/'})
])
At the moment I am able to capture when the router has instantiated or destroyed a particular component when it moves from one to the next. This is great, but when the the previous component is destroyed I am not able to apply an on leave transition animation before the next component is initialized.
class HomeCmp implements OnActivate, onDeactivate{
onActivate(next: ComponentInstruction, prev: ComponentInstruction) {
//This works
TweenMax.fromTo($(".title"), 1, {opacity: 0}, {opacity: 1});
}
onDeactivate(next: ComponentInstruction, prev: ComponentInstruction) {
//This get ignored
TweenMax.fromTo($(".title"), 1, {opacity: 0}, {opacity: 1});
}
}
It seems like there is a solution to this using promises. Angular.io's API preview they state:
If onDeactivate returns a promise, the route change will wait until the promise settles.
and
If onActivate returns a promise, the route change will wait until the promise settles to instantiate and activate child components.
https://angular.io/docs/ts/latest/api/
I am super brand new to promises so I mashed this together into my code which solved the problem of my current component being destroyed on initialization of the next one, but then it never gets destroyed, it only creates a new instance of it. Every time I navigate back to it, it will create a new instance resulting in multiple copies.
onDeactivate(next: ComponentInstruction, prev: ComponentInstruction) {
function ani(){
TweenMax.fromTo($(".title"), 1, {opacity: 1}, {opacity: 0});
}
var aniPromise = ani();
aniPromise.then(function (ani) {
ani();
});
}
So to recap, the router should be able to wait for the current component to finish it's business before destroying it and initializing the next component.
I hope that all makes sense and I really appreciate the help!
See Question&Answers more detail:
os