Reputation: 2770
I have a container that expands/shrinks. There is an element inside that container that should fade in when the container expands and fade out when the container shrinks.
My Problem
How do I make all animations execute in parallel under both expand/shrink conditions?
Note the use of ngIf. This is intentional as it destroys the element at the end of the animation sequence.
Here is a plunkr of my current state: https://embed.plnkr.co/TXYoGf9QpErWmlRvQF9Z/
The component class:
export class App {
expanded = true;
toggleExpandedState() {
this.expanded = !this.expanded;
}
constructor() {
}
}
The template:
<div class="container" [@expansionTrigger]="expanded">
<div class="constant-item"></div>
<div class="fade-item" [@stateAnimation] *ngIf="expanded"></div>
</div>
<button (click)="toggleExpandedState()">Toggle Fade</button>
and the component animation:
trigger('expansionTrigger', [
state('1', style({
width: '250px'
})),
state('0', style({
width: '160px'
})),
transition('0 => 1', animate('200ms ease-in')),
transition('1 => 0', animate('200ms ease-out'))
]),
trigger('stateAnimation', [
transition(':enter', [
style({
opacity: 0
}),
animate('200ms 350ms ease-in', style({
opacity: 1
}))
]),
transition(':leave', [
style({
opacity: 1
})
animate('1s', style({
opacity: 0
}))
])
])
Upvotes: 10
Views: 4515
Reputation: 2770
In hopes to save others the frustration, it looks like it is a bug with Angular 4.
There are currently two open issues on Github that appear to be pretty closely related:
https://github.com/angular/angular/issues/15798
https://github.com/angular/angular/issues/15753
Update
According to the github issue, the animation bug won't be fixed to work as it once did in Angular2. Instead query()
and animateChild()
are being introduced. The new animation features are available as of 4.2.0-rc2.
In summary:
Component Definition
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
<button (click)="toggle()">Toggle</button>
<div *ngIf="show" @ngIfAnimation>
<h3 @easeInOut>I'm inside ngIf</h3>
</div>
</div>
`,
animations: [
trigger('ngIfAnimation', [
transition(':enter, :leave', [
query('@*', animateChild())
])
])
trigger('easeInOut', [
transition('void => *', [
style({
opacity: 0
}),
animate("1s ease-in-out", style({
opacity: 1
}))
]),
transition('* => void', [
style({
opacity: 1
}),
animate("1s ease-in-out", style({
opacity: 0
}))
])
])
]]
})
export class App {
name:string;
show:boolean = false;
constructor() {
this.name = `Angular! v${VERSION.full}`
}
toggle() {
this.show = !this.show;
}
}
There is a working example available here: https://embed.plnkr.co/RJgAunJfibBKNFt0DCZS/
Upvotes: 3
Reputation: 9753
here is what you'll need to do:
plnkr here: https://plnkr.co/edit/AQEVh3GGc31ivQZMp223?p=preview
remove *ngIf="expanded"
use [@stateAnimation]="expanded"
replace your stateAnimate
trigger with this:
trigger('stateAnimation', [
state('1', style({ opacity: 0 })),
state('0', style({opacity: 1})),
transition('0 => 1', animate('200ms ease-in')),
transition('1 => 0', animate('200ms ease-out'))
])
here is the full code:
//our root app component
import {Component, NgModule, VERSION,
Output,
trigger,
state,
style,
transition,
animate,
} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
@Component({
selector: 'my-app',
template: `
<div class="container" [@expansionTrigger]="expanded">
<div class="constant-item"></div>
<div class="fade-item" [@stateAnimation]="expanded"></div>
</div>
<button (click)="toggleExpandedState()">Toggle Fade</button>
`,
animations: [
trigger('expansionTrigger', [
state('1', style({ width: '250px' })),
state('0', style({width:'160px'})),
transition('0 => 1', animate('200ms ease-in')),
transition('1 => 0', animate('200ms ease-out'))
]),
trigger('stateAnimation', [
state('1', style({ opacity: 0 })),
state('0', style({opacity: 1})),
transition('0 => 1', animate('200ms ease-in')),
transition('1 => 0', animate('200ms ease-out'))
])
]
})
export class App {
expanded = true;
toggleExpandedState() {
this.expanded = !this.expanded;
}
constructor() {
}
}
@NgModule({
imports: [ BrowserModule, BrowserAnimationsModule ],
declarations: [ App ],
bootstrap: [ App ]
})
export class AppModule {}
Upvotes: 2