Search code examples
angularanimationtransition

angular 6 animation *ngIf, transition not work


The project presents two variants of animation.

Animation Option 1, trigger('animationOption1')
Works without complaints.

Animation Option 2, trigger('animationOption2')
transition doesn't work here.

Online check this project in StackBlitz.com

app.component.html

<h1>Animation Option 1</h1>
<div (click)="changeDivState()"
     [@animationOption1]="clickedDivState"
>Click Me
</div>

<h1>Animation Option 2</h1>
<button (click)="toggleMenu()">Click Me</button>
<ul *ngIf="isMenuOpen"
    [@animationOption2]="isMenuOpen ? 'open': 'close'"
>
  <li>Menu Item 1</li>
  <li>Menu Item 2</li>
  <li>Menu Item 3</li>
</ul>

app.component.ts

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  animations: [
    trigger('animationOption1', [
      state('start', style({
        backgroundColor: 'yellow',
        width: '150px',
        height: '150px'
      })),
      state('end', style({
        backgroundColor: 'green',
        width: '300px',
        height: '300px'
      })),
      transition('start => end', animate(1500)),
      transition('end => start', animate('800ms 0.5s ease-out'))
    ]),
    trigger('animationOption2', [
      state('close', style({
        opacity: 0,
        backgroundColor: 'yellow'
      })),
      state('open', style({
        opacity: 1,
        backgroundColor: 'green'
      })),
      transition('close <=> open', animate(3000)),
    ])
  ]
})
export class AppComponent {
  isMenuOpen = false;

  clickedDivState = 'start';

  changeDivState() {
    this.clickedDivState = 'end';
    setTimeout(() => {
      this.clickedDivState = 'start';
    }, 3000);
  }

  toggleMenu(): void {
    this.isMenuOpen = !this.isMenuOpen;
  }
}

Googling did not lead to a solution.


Solution

  • To get this to work you will need to remove the *ngIf="isMenuOpen" on the <ul>. Angular is unable to calculate the transition between the closed/open states as the element simply does not exist when isMenuOpen is false.

    Here is a StackBlitz showing the animation in action with *ngIf removed.

    Alternatively you can utilize entering/leaving states to use in conjunction with *ngIf. It would look like this:

    trigger('animationOption2', [      
      transition(':enter', [
        style({ backgroundColor: 'yellow' }),
        animate(300)
      ]),
      transition(':leave', [
        animate(300, style({ backgroundColor: 'yellow' }))
      ]),
      state('*', style({ backgroundColor: 'green' })),
    ])
    

    Here is a StackBlitz in action.