This is the archived documentation for Angular v5. Please visit angular.io to see documentation for the current version of Angular.

transition

npm Package @angular/animations
Module import { transition } from '@angular/animations';
Source animations/src/animation_metadata.ts
      
      function transition(stateChangeExpr: string | ((fromState: string, toState: string) => boolean), steps: AnimationMetadata | AnimationMetadata[], options: AnimationOptions | null = null): AnimationTransitionMetadata;
    

Description

transition is an animation-specific function that is designed to be used inside of Angular's animation DSL language. If this information is new, please navigate to the component animations metadata page to gain a better understanding of how animations in Angular are used.

transition declares the sequence of animation steps that will be run when the provided stateChangeExpr value is satisfied. The stateChangeExpr consists of a state1 => state2 which consists of two known states (use an asterix (*) to refer to a dynamic starting and/or ending state).

A function can also be provided as the stateChangeExpr argument for a transition and this function will be executed each time a state change occurs. If the value returned within the function is true then the associated animation will be run.

Animation transitions are placed within an animation trigger. For an transition to animate to a state value and persist its styles then one or more animation states is expected to be defined.

Usage

An animation transition is kicked off the stateChangeExpr predicate evaluates to true based on what the previous state is and what the current state has become. In other words, if a transition is defined that matches the old/current state criteria then the associated animation will be triggered.

      
      // all transition/state changes are defined within an animation trigger
trigger("myAnimationTrigger", [
  // if a state is defined then its styles will be persisted when the
  // animation has fully completed itself
  state("on", style({ background: "green" })),
  state("off", style({ background: "grey" })),

  // a transition animation that will be kicked off when the state value
  // bound to "myAnimationTrigger" changes from "on" to "off"
  transition("on => off", animate(500)),

  // it is also possible to do run the same animation for both directions
  transition("on <=> off", animate(500)),

  // or to define multiple states pairs separated by commas
  transition("on => off, off => void", animate(500)),

  // this is a catch-all state change for when an element is inserted into
  // the page and the destination state is unknown
  transition("void => *", [
    style({ opacity: 0 }),
    animate(500)
  ]),

  // this will capture a state change between any states
  transition("* => *", animate("1s 0s")),

  // you can also go full out and include a function
  transition((fromState, toState) => {
    // when `true` then it will allow the animation below to be invoked
    return fromState == "off" && toState == "on";
  }, animate("1s 0s"))
])
    

The template associated with this component will make use of the myAnimationTrigger animation trigger by binding to an element within its template code.

      
      <!-- somewhere inside of my-component-tpl.html -->
<div [@myAnimationTrigger]="myStatusExp">...</div>
    

The final animate call

If the final step within the transition steps is a call to animate() that only uses a timing value with no style data then it will be automatically used as the final animation arc for the element to animate itself to the final state. This involves an automatic mix of adding/removing CSS styles so that the element will be in the exact state it should be for the applied state to be presented correctly.

      
      // start off by hiding the element, but make sure that it animates properly to whatever state
// is currently active for "myAnimationTrigger"
transition("void => *", [
  style({ opacity: 0 }),
  animate(500)
])
    

Using :enter and :leave

Given that enter (insertion) and leave (removal) animations are so common, the transition function accepts both :enter and :leave values which are aliases for the void => * and * => void state changes.

      
      transition(":enter", [
  style({ opacity: 0 }),
  animate(500, style({ opacity: 1 }))
]),
transition(":leave", [
  animate(500, style({ opacity: 0 }))
])
    

Boolean values

if a trigger binding value is a boolean value then it can be matched using a transition expression that compares true and false or 1 and 0.

      
      // in the template
<div [@openClose]="open ? true : false">...</div>

// in the component metadata
trigger('openClose', [
  state('true', style({ height: '*' })),
  state('false', style({ height: '0px' })),
  transition('false <=> true', animate(500))
])
    

Using :increment and :decrement

In addition to the :enter and :leave transition aliases, the :increment and :decrement aliases can be used to kick off a transition when a numeric value has increased or decreased in value.

      
      import {group, animate, query, transition, style, trigger} from '@angular/animations';
import {Component} from '@angular/core';

@Component({
  selector: 'banner-carousel-component',
  styles: [`
    .banner-container {
       position:relative;
       height:500px;
       overflow:hidden;
     }
    .banner-container > .banner {
       position:absolute;
       left:0;
       top:0;
       font-size:200px;
       line-height:500px;
       font-weight:bold;
       text-align:center;
       width:100%;
     }
  `],
  template: `
    <button (click)="previous()">Previous</button>
    <button (click)="next()">Next</button>
    <hr>
    <div [@bannerAnimation]="selectedIndex" class="banner-container">
      <div class="banner" *ngFor="let banner of banners"> {{ banner }} </div>
    </div>
  `,
  animations: [
    trigger('bannerAnimation', [
      transition(":increment", group([
        query(':enter', [
          style({ left: '100%' }),
          animate('0.5s ease-out', style('*'))
        ]),
        query(':leave', [
          animate('0.5s ease-out', style({ left: '-100%' }))
        ])
      ])),
      transition(":decrement", group([
        query(':enter', [
          style({ left: '-100%' }),
          animate('0.5s ease-out', style('*'))
        ]),
        query(':leave', [
          animate('0.5s ease-out', style({ left: '100%' }))
        ])
      ]))
    ])
  ]
})
class BannerCarouselComponent {
  allBanners: string[] = ['1', '2', '3', '4'];
  selectedIndex: number = 0;

  get banners() {
     return [this.allBanners[this.selectedIndex]];
  }

  previous() {
    this.selectedIndex = Math.max(this.selectedIndex - 1, 0);
  }

  next() {
    this.selectedIndex = Math.min(this.selectedIndex + 1, this.allBanners.length - 1);
  }
}
    
      
      import {animate, state, style, transition, trigger} from '@angular/animations';
import {Component, NgModule} from '@angular/core';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';

@Component({
  selector: 'example-app',
  styles: [`
    .toggle-container {
      background-color:white;
      border:10px solid black;
      width:200px;
      text-align:center;
      line-height:100px;
      font-size:50px;
      box-sizing:border-box;
      overflow:hidden;
    }
  `],
  animations: [trigger(
      'openClose',
      [
        state('collapsed, void', style({height: '0px', color: 'maroon', borderColor: 'maroon'})),
        state('expanded', style({height: '*', borderColor: 'green', color: 'green'})),
        transition(
            'collapsed <=> expanded', [animate(500, style({height: '250px'})), animate(500)])
      ])],
  template: `
    <button (click)="expand()">Open</button>
    <button (click)="collapse()">Closed</button>
    <hr />
    <div class="toggle-container" [@openClose]="stateExpression">
      Look at this box
    </div>
  `
})
export class MyExpandoCmp {
  stateExpression: string;
  constructor() { this.collapse(); }
  expand() { this.stateExpression = 'expanded'; }
  collapse() { this.stateExpression = 'collapsed'; }
}

@NgModule(
    {imports: [BrowserAnimationsModule], declarations: [MyExpandoCmp], bootstrap: [MyExpandoCmp]})
export class AppModule {
}