Solución:
Primero, cree un archivo donde definiría sus animaciones y exportarlas. Solo para que quede más claro en su app.component.ts
En el siguiente ejemplo, utilicé una altura máxima del div que va de 0px (cuando está oculto) a 500px, pero lo cambiaría según lo que necesite.
Esta animación usa estados (dentro y fuera), que se alternarán cuando hagamos clic en el botón, que ejecutará la animación.
animaciones.ts
import { trigger, state, style, transition,
animate, group, query, stagger, keyframes
} from '@angular/animations';
export const SlideInOutAnimation = [
trigger('slideInOut', [
state('in', style({
'max-height': '500px', 'opacity': '1', 'visibility': 'visible'
})),
state('out', style({
'max-height': '0px', 'opacity': '0', 'visibility': 'hidden'
})),
transition('in => out', [group([
animate('400ms ease-in-out', style({
'opacity': '0'
})),
animate('600ms ease-in-out', style({
'max-height': '0px'
})),
animate('700ms ease-in-out', style({
'visibility': 'hidden'
}))
]
)]),
transition('out => in', [group([
animate('1ms ease-in-out', style({
'visibility': 'visible'
})),
animate('600ms ease-in-out', style({
'max-height': '500px'
})),
animate('800ms ease-in-out', style({
'opacity': '1'
}))
]
)])
]),
]
Luego, en el componente de su aplicación, importamos la animación y creamos el método que alternará el estado de la animación.
app.component.ts
import { SlideInOutAnimation } from './animations';
@Component({
...
animations: [SlideInOutAnimation]
})
export class AppComponent {
animationState="in";
...
toggleShowDiv(divName: string) {
if (divName === 'divA') {
console.log(this.animationState);
this.animationState = this.animationState === 'out' ? 'in' : 'out';
console.log(this.animationState);
}
}
}
Y así es como tu app.component.html se vería así:
<div class="wrapper">
<button (click)="toggleShowDiv('divA')">TOGGLE DIV</button>
<div [@slideInOut]="animationState" style="height: 100px; background-color: red;">
THIS DIV IS ANIMATED</div>
<div class="content">THIS IS CONTENT DIV</div>
</div>
slideInOut se refiere al disparador de animación definido en animations.ts
Aquí hay un ejemplo de StackBlitz que he creado: https://stackblitz.com/edit/angular-muvaqu
Nota al margen: si alguna vez ocurre un error y le pide que agregue BrowserAnimationsModule, solo impórtalo en tu app.module.ts:
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
@NgModule({
imports: [ ..., BrowserAnimationsModule ],
...
})
Prefiero el operador comodín cuando trabajo con transiciones de altura para permitir el contenido dinámico de altura.
// Bind to true/false states via 0 and 1 values
trigger('slideUpDown', [
state('0', style({ 'max-height': '*', opacity: 1 })),
state('1', style({ 'max-height': '0px', opacity: 0 })),
transition(':enter', animate('400ms ease-in-out')),
transition('* => *', animate('400ms ease-in-out')),
])
uso:
<div #someDiv [@slideUpDown]="someDiv.state"></div>
en otro lugar o en la plantilla, puede alternar el estado.
<button (click)="someDiv.state = !someDiv.state"></button>
Esta es una forma limpia y fácil de implementar una animación de deslizamiento hacia abajo en angular 2+
my-component.ts
import { animate, style, transition, trigger } from '@angular/animations';
@Component({
animations: [
trigger('slideDownUp', [
transition(':enter', [style({ height: 0 }), animate(500)]),
transition(':leave', [animate(500, style({ height: 0 }))]),
]),
],
})
my-component.html
<div @slideDownUp *ngIf="isShowing" class="box">
I am the content of the div!
</div>
my-component.scss
.box {
overflow: hidden;
}