Welcome to Knowledge Base!

KB at your finger tips

This is one stop global knowledge base where you can learn about all the products, solutions and support features.

Categories
All

Web-Angular

Angular - Angular package format

Angular package format link

This document describes the Angular Package Format (APF). APF is an Angular specific specification for the structure and format of npm packages that is used by all first-party Angular packages ( @angular/core , @angular/material , etc.) and most third-party Angular libraries.

APF enables a package to work seamlessly under most common scenarios that use Angular. Packages that use APF are compatible with the tooling offered by the Angular team as well as wider JavaScript ecosystem. It is recommended that third-party library developers follow the same npm package format.

APF is versioned along with the rest of Angular, and every major version improves the package format. You can find the versions of the specification prior to v13 in this google doc.

Why specify a package format? link

In today's JavaScript landscape, developers consume packages in many different ways, using many different toolchains (Webpack, rollup, esbuild, etc.). These tools may understand and require different inputs - some tools may be able to process the latest ES language version, while others may benefit from directly consuming an older ES version.

The Angular distribution format supports all of the commonly used development tools and workflows, and adds emphasis on optimizations that result either in smaller application payload size or faster development iteration cycle (build time).

Developers can rely on Angular CLI and ng-packagr (a build tool Angular CLI uses) to produce packages in the Angular package format. See the Creating Libraries guide for more details.

File layout link

The following example shows a simplified version of the @angular/core package's file layout, with an explanation for each file in the package.

node_modules/@angular/core
README.md
package.json
index.d.ts
esm2020
core.mjs
index.mjs
public_api.mjs
testing
fesm2015
core.mjs
core.mjs.map
testing.mjs
testing.mjs.map
fesm2020
core.mjs
core.mjs.map
testing.mjs
testing.mjs.map
testing
index.d.ts

This table describes the file layout under node_modules/@angular/core annotated to describe the purpose of files and directories:

Files Purpose
README.md Package README, used by npmjs web UI.
package.json Primary package.json , describing the package itself as well as all available entrypoints and code formats. This file contains the "exports" mapping used by runtimes and tools to perform module resolution.
index.d.ts Bundled .d.ts for the primary entrypoint @angular/core .
esm2020/
core.mjs
index.mjs
public_api.mjs
Tree of @angular/core sources in unflattened ES2020 format.
esm2020/testing/ Tree of the @angular/core/testing entrypoint in unflattened ES2020 format.
fesm2015/
core.mjs
core.mjs.map
testing.mjs
testing.mjs.map
Code for all entrypoints in a flattened (FESM) ES2015 format, along with source maps.
fesm2020/
core.mjs
core.mjs.map
testing.mjs
testing.mjs.map
Code for all entrypoints in flattened (FESM) ES2020 format, along with source maps.
testing/ Directory representing the "testing" entrypoint.
testing/index.d.ts Bundled .d.ts for the @angular/core/testing entrypoint.

package.json link

The primary package.json contains important package metadata, including the following:

  • It declares the package to be in EcmaScript Module (ESM) format

  • It contains an "exports" field which defines the available source code formats of all entrypoints

  • It contains keys which define the available source code formats of the primary @angular/core entrypoint, for tools which do not understand "exports" . These keys are considered deprecated, and could be removed as the support for "exports" rolls out across the ecosystem.

  • It declares whether the package contains side effects

ESM declaration link

The top-level package.json contains the key:

      
      {
  "type": "module"
}
    

This informs resolvers that code within the package is using EcmaScript Modules as opposed to CommonJS modules.

"exports" link

The "exports" field has the following structure:

      
      "exports": {
  "./schematics/*": {
    "default": "./schematics/*.js"
  },
  "./package.json": {
    "default": "./package.json"
  },
  ".": {
    "types": "./core.d.ts",
    "esm2020": "./esm2020/core.mjs",
    "es2020": "./fesm2020/core.mjs",
    "es2015": "./fesm2015/core.mjs",
    "node": "./fesm2015/core.mjs",
    "default": "./fesm2020/core.mjs"
  },
  "./testing": {
    "types": "./testing/testing.d.ts",
    "esm2020": "./esm2020/testing/testing.mjs",
    "es2020": "./fesm2020/testing.mjs",
    "es2015": "./fesm2015/testing.mjs",
    "node": "./fesm2015/testing.mjs",
    "default": "./fesm2020/testing.mjs"
  }
}
    

Of primary interest are the "." and the "./testing" keys, which define the available code formats for the @angular/core primary entrypoint and the @angular/core/testing secondary entrypoint, respectively. For each entrypoint, the available formats are:

Formats Details
Typings ( .d.ts files) .d.ts files are used by TypeScript when depending on a given package.
es2020 ES2020 code flattened into a single source file.
es2015 ES2015 code flattened into a single source file.
esm2020 ES2020 code in unflattened source files (this format is included for experimentation - see this discussion of defaults for details).

Tooling that is aware of these keys may preferentially select a desirable code format from "exports" . The remaining 2 keys control the default behavior of tooling:

  • "node" selects flattened ES2015 code when the package is loaded in Node.

    This format is used due to the requirements of zone.js , which does not support native async / await ES2017 syntax. Therefore, Node is instructed to use ES2015 code, where async / await structures have been downleveled into Promises.

  • "default" selects flattened ES2020 code for all other consumers.

Libraries may want to expose additional static files which are not captured by the exports of the JavaScript-based entry-points such as Sass mixins or pre-compiled CSS.

For more information, see Managing assets in a library.

Legacy resolution keys link

In addition to "exports" , the top-level package.json also defines legacy module resolution keys for resolvers that don't support "exports" . For @angular/core these are:

      
      {
  "fesm2020": "./fesm2020/core.mjs",
  "fesm2015": "./fesm2015/core.mjs",
  "esm2020": "./esm2020/core.mjs",
  "typings": "./core.d.ts",
  "module": "./fesm2015/core.mjs",
  "es2020": "./fesm2020/core.mjs",
}
    

As shown in the preceding code snippet, a module resolver can use these keys to load a specific code format.

NOTE :
Instead of "default" , "module" selects the format both for Node as well as any tooling not configured to use a specific key. As with "node" , ES2015 code is selected due to the constraints of ZoneJS.

Side effects link

The last function of package.json is to declare whether the package has side effects.

      
      {
  "sideEffects": false
}
    

Most Angular packages should not depend on top-level side effects, and thus should include this declaration.

Entrypoints and code splitting link

Packages in the Angular Package Format contain one primary entrypoint and zero or more secondary entrypoints (for example, @angular/common/http ). Entrypoints serve several functions.

  1. They define the module specifiers from which users import code (for example, @angular/core and @angular/core/testing ).

    Users typically perceive these entrypoints as distinct groups of symbols, with different purposes or capability.

    Specific entrypoints might only be used for special purposes, such as testing. Such APIs can be separated out from the primary entrypoint to reduce the chance of them being used accidentally or incorrectly.

  2. They define the granularity at which code can be lazily loaded.

    Many modern build tools are only capable of "code splitting" (aka lazy loading) at the ES Module level. The Angular Package Format uses primarily a single "flat" ES Module per entry point. This means that most build tooling is not able to split code with a single entry point into multiple output chunks.

The general rule for APF packages is to use entrypoints for the smallest sets of logically connected code possible. For example, the Angular Material package publishes each logical component or set of components as a separate entrypoint - one for Button, one for Tabs, etc. This allows each Material component to be lazily loaded separately, if desired.

Not all libraries require such granularity. Most libraries with a single logical purpose should be published as a single entrypoint. @angular/core for example uses a single entrypoint for the runtime, because the Angular runtime is generally used as a single entity.

Resolution of secondary entry points link

Secondary entrypoints can be resolved via the "exports" field of the package.json for the package.

README.md link

The README file in the Markdown format that is used to display description of a package on npm and GitHub.

Example README content of @angular/core package:

      
      Angular
=======

The sources for this package are in the main [Angular](https://github.com/angular/angular) repo.Please file issues and pull requests against that repo.

License: MIT
    

Partial compilation link

Libraries in the Angular Package Format must be published in "partial compilation" mode. This is a compilation mode for ngc which produces compiled Angular code that is not tied to a specific Angular runtime version, in contrast to the full compilation used for applications, where the Angular compiler and runtime versions must match exactly.

To partially compile Angular code, use the compilationMode flag in the angularCompilerOptions property of your tsconfig.json :

      
      {
  
  "angularCompilerOptions": {
    "compilationMode": "partial",
  }
}
    

Partially compiled library code is then converted to fully compiled code during the application build process by the Angular CLI.

If your build pipeline does not use the Angular CLI then refer to the Consuming partial ivy code outside the Angular CLI guide.

Optimizations link

Flattening of ES modules link

The Angular Package Format specifies that code be published in "flattened" ES module format. This significantly reduces the build time of Angular applications as well as download and parse time of the final application bundle. Please check out the excellent post "The cost of small modules" by Nolan Lawson.

The Angular compiler can generate index ES module files. Tools like Rollup can use these files to generate flattened modules in a Flattened ES Module (FESM) file format.

FESM is a file format created by flattening all ES Modules accessible from an entrypoint into a single ES Module. It's formed by following all imports from a package and copying that code into a single file while preserving all public ES exports and removing all private imports.

The abbreviated name, FESM, pronounced phe-som , can be followed by a number such as FESM5 or FESM2015. The number refers to the language level of the JavaScript inside the module. Accordingly a FESM5 file would be ESM+ES5 and include import/export statements and ES5 source code.

To generate a flattened ES Module index file, use the following configuration options in your tsconfig.json file:

      
      {
  "compilerOptions": {
    
    "module": "esnext",
    "target": "es2020",
    
  },
  "angularCompilerOptions": {
    
    "flatModuleOutFile": "my-ui-lib.js",
    "flatModuleId": "my-ui-lib"
  }
}
    

Once the index file (for example, my-ui-lib.js ) is generated by ngc, bundlers and optimizers like Rollup can be used to produce the flattened ESM file.

Note about the defaults in package.json link

As of webpack v4, the flattening of ES modules optimization should not be necessary for webpack users. It should be possible to get better code-splitting without flattening of modules in webpack. In practice, size regressions can still be seen when using unflattened modules as input for webpack v4. This is why module and es2020 package.json entries still point to FESM files. This issue is being investigated. It is expected to switch the module and es2020 package.json entry points to unflattened files after the size regression issue is resolved. The APF currently includes unflattened ESM2020 code for the purpose of validating such a future change.

"sideEffects" flag link

By default, EcmaScript Modules are side-effectful: importing from a module ensures that any code at the top level of that module should run. This is often undesirable, as most side-effectful code in typical modules is not truly side-effectful, but instead only affects specific symbols. If those symbols are not imported and used, it's often desirable to remove them in an optimization process known as tree-shaking, and the side-effectful code can prevent this.

Build tools such as Webpack support a flag which allows packages to declare that they do not depend on side-effectful code at the top level of their modules, giving the tools more freedom to tree-shake code from the package. The end result of these optimizations should be smaller bundle size and better code distribution in bundle chunks after code-splitting. This optimization can break your code if it contains non-local side-effects - this is however not common in Angular applications and it's usually a sign of bad design. The recommendation is for all packages to claim the side-effect free status by setting the sideEffects property to false , and that developers follow the Angular Style Guide which naturally results in code without non-local side-effects.

More info: webpack docs on side effects

ES2020 language level link

ES2020 Language level is now the default language level that is consumed by Angular CLI and other tooling. The Angular CLI down-levels the bundle to a language level that is supported by all targeted browsers at application build time.

d.ts bundling / type definition flattening link

As of APF v8 it is now preferred to run API Extractor, to bundle TypeScript definitions so that the entire API appears in a single file.

In prior APF versions each entry point would have a src directory next to the .d.ts entry point and this directory contained individual d.ts files matching the structure of the original source code. While this distribution format is still allowed and supported, it is highly discouraged because it confuses tools like IDEs that then offer incorrect autocompletion, and allows users to depend on deep-import paths which are typically not considered to be public API of a library or a package.

Tslib link

As of APF v10, it is recommended to add tslib as a direct dependency of your primary entry-point. This is because the tslib version is tied to the TypeScript version used to compile your library.

Examples link

  • @angular/core package
  • @angular/material package

Definition of terms link

The following terms are used throughout this document intentionally. In this section are the definitions of all of them to provide additional clarity.

Package link

The smallest set of files that are published to NPM and installed together, for example @angular/core . This package includes a manifest called package.json, compiled source code, typescript definition files, source maps, metadata, etc. The package is installed with npm install @angular/core .

Symbol link

A class, function, constant, or variable contained in a module and optionally made visible to the external world via a module export.

Module link

Short for ECMAScript Modules. A file containing statements that import and export symbols. This is identical to the definition of modules in the ECMAScript spec.

ESM link

Short for ECMAScript Modules (see above).

FESM link

Short for Flattened ES Modules and consists of a file format created by flattening all ES Modules accessible from an entry point into a single ES Module.

Module ID link

The identifier of a module used in the import statements (for example, @angular/core ). The ID often maps directly to a path on the filesystem, but this is not always the case due to various module resolution strategies.

Module specifier link

A module identifier (see above).

Module resolution strategy link

Algorithm used to convert Module IDs to paths on the filesystem. Node.js has one that is well specified and widely used, TypeScript supports several module resolution strategies, Closure Compiler has yet another strategy.

Module format link

Specification of the module syntax that covers at minimum the syntax for the importing and exporting from a file. Common module formats are CommonJS (CJS, typically used for Node.js applications) or ECMAScript Modules (ESM). The module format indicates only the packaging of the individual modules, but not the JavaScript language features used to make up the module content. Because of this, the Angular team often uses the language level specifier as a suffix to the module format, (for example, ESM+ES2015 specifies that the module is in ESM format and contains code down-leveled to ES2015).

Bundle link

An artifact in the form of a single JS file, produced by a build tool (for example, Webpack or Rollup) that contains symbols originating in one or more modules. Bundles are a browser-specific workaround that reduce network strain that would be caused if browsers were to start downloading hundreds if not tens of thousands of files. Node.js typically doesn't use bundles. Common bundle formats are UMD and System.register.

Language level link

The language of the code (ES2015 or ES2020). Independent of the module format.

Entry point link

A module intended to be imported by the user. It is referenced by a unique module ID and exports the public API referenced by that module ID. An example is @angular/core or @angular/core/testing . Both entry points exist in the @angular/core package, but they export different symbols. A package can have many entry points.

Deep import link

A process of retrieving symbols from modules that are not Entry Points. These module IDs are usually considered to be private APIs that can change over the lifetime of the project or while the bundle for the given package is being created.

Top-Level import link

An import coming from an entry point. The available top-level imports are what define the public API and are exposed in "@angular/name" modules, such as @angular/core or @angular/common .

Tree-shaking link

The process of identifying and removing code not used by an application - also known as dead code elimination. This is a global optimization performed at the application level using tools like Rollup, Closure Compiler, or Terser.

AOT compiler link

The Ahead of Time Compiler for Angular.

Flattened type definitions link

The bundled TypeScript definitions generated from API Extractor.

Last reviewed on Mon Feb 28 2022

Angular - Animate state and style

Animate state and style link

You can define a set of styles together to make up a specific state for animating elements and transitions. These states represent style at certain points in your animations that you can animate to and from. For example, you can animate a state as the starting point to a different state and the end of an animation.

What is a state? link

A state is the condition of an animation. The Angular state() function takes two parameters: a unique name and a style. There is also an optional parameter.

Why would you want to use state? link

Aliasing a set of styles and allows you to reference that alias for animations in general. This can make animations more readable or more understandable at a glance. You can give animations a useful and descriptive state name, which allows you to quickly understand the purpose of that animation state.

Use Angular's state() function to define different states to call at the end of each transition. This function takes two arguments: A unique name like open or closed and a style() function.

Use the style() function to define a set of styles to associate with a given state name. You must use camelCase for style attributes that contain dashes, such as backgroundColor or wrap them in quotes, such as 'background-color' .

Angular's state() function works with the style⁣­(⁠) function to set CSS style attributes. In this code snippet, multiple style attributes are set at the same time for the state. In the open state, the button has a height of 200 pixels, an opacity of 1, and a yellow background color.

src/app/open-close.component.ts
      
      // ...
state('open', style({
  height: '200px',
  opacity: 1,
  backgroundColor: 'yellow'
})),
    

In the following closed state, the button has a height of 100 pixels, an opacity of 0.8, and a background color of blue.

src/app/open-close.component.ts
      
      state('closed', style({
  height: '100px',
  opacity: 0.8,
  backgroundColor: 'blue'
})),
    
Last reviewed on Fri Oct 28 2022
Read article

Angular - Animation API summary

Animation API summary link

The functional API provided by the @angular/animations module provides a domain-specific language (DSL) for creating and controlling animations in Angular applications. See the API reference for a complete listing and syntax details of the core functions and related data structures.

Function name What it does
trigger() Kicks off the animation and serves as a container for all other animation function calls. HTML template binds to triggerName . Use the first argument to declare a unique trigger name. Uses array syntax.
style() Defines one or more CSS styles to use in animations. Controls the visual appearance of HTML elements during animations. Uses object syntax.
state() Creates a named set of CSS styles that should be applied on successful transition to a given state. The state can then be referenced by name within other animation functions.
animate() Specifies the timing information for a transition. Optional values for delay and easing . Can contain style() calls within.
transition() Defines the animation sequence between two named states. Uses array syntax.
keyframes() Allows a sequential change between styles within a specified time interval. Use within animate() . Can include multiple style() calls within each keyframe() . Uses array syntax.
group() Specifies a group of animation steps ( inner animations ) to be run in parallel. Animation continues only after all inner animation steps have completed. Used within sequence() or transition() .
query() Finds one or more inner HTML elements within the current element.
sequence() Specifies a list of animation steps that are run sequentially, one by one.
stagger() Staggers the starting time for animations for multiple elements.
animation() Produces a reusable animation that can be invoked from elsewhere. Used together with useAnimation() .
useAnimation() Activates a reusable animation. Used with animation() .
animateChild() Allows animations on child components to be run within the same timeframe as the parent.
Last reviewed on Fri Oct 28 2022
Read article

Angular - Animation transition and timing

Animation transition and timing link

An animation transition specifies changes that occur between one state and another. Set the transition to make the change less abrupt. An animation transition specifies the changes that occur between one state and another.

Animation transition() function defined link

The transition() function accepts two arguments:

An expression that defines the direction between two transition states An expression that accepts one or a series of animate() steps

Use the animate() function of a transition to define:

  • Length
  • Delay
  • Easing
  • Style function for defining styles while transitions are taking place

Use the animate() function to define the keyframes() function for multi-step animations. These definitions are placed in the second argument of the animate() function.

Animation metadata: duration, delay, and easing link

The animate() function accepts the timings and styles input parameters.

The timings parameter takes either a number or a string defined in three parts.

      
      animate (duration)
    

or

      
      animate ('duration delay easing')
    

The first part, duration , is required. The duration can be expressed in milliseconds as a number without quotes, or in seconds with quotes and a time specifier. For example, a duration of a tenth of a second can be expressed as follows:

  • As a plain number, in milliseconds: 100

  • In a string, as milliseconds: '100ms'

  • In a string, as seconds: '0.1s'

The second argument, delay , has the same syntax as duration . For example:

  • Wait for 100 ms and then run for 200 ms: '0.2s 100ms'

The third argument, easing , controls how the animation accelerates and decelerates during its runtime. For example, ease-in causes the animation to begin slowly, and to pick up speed as it progresses.

  • Wait for 100 ms, run for 200 ms. Use a deceleration curve to start out fast and slowly decelerate to a resting point:

          
          0.2s 100ms ease-out
        
  • Run for 200 ms, with no delay. Use a standard curve to start slow, speed up in the middle, and then decelerate slowly at the end:

          
          0.2s ease-in-out
        
  • Start immediately, run for 200 ms. Use an acceleration curve to start slow and end at full velocity:

          
          

    The code sample is missing.

    0.2s ease-in

NOTE :
See the Material Design website's topic on Natural easing curves for general information on easing curves.

This example provides a state transition from open to closed with a 1-second transition between states.

src/app/open-close.component.ts
      
      transition('open => closed', [
  animate('1s')
]),
    

In the preceding code snippet, the => operator indicates unidirectional transitions, and <=> is bidirectional. Within the transition, animate() specifies how long the transition takes. In this case, the state change from open to closed takes 1 second, expressed here as 1s .

This example adds a state transition from the closed state to the open state with a 0.5-second transition animation arc.

src/app/open-close.component.ts
      
      transition('closed => open', [
  animate('0.5s')
]),
    

NOTE :
Using styles within state and transition functions:

  • Use state() to define styles that are applied at the end of each transition, they persist after the animation completes

  • Use transition() to define intermediate styles, which create the illusion of motion during the animation

  • When animations are turned off, transition() styles can be skipped, but state() styles can't

  • Include multiple state pairs within the same transition() argument:

          
          transition( 'on => off, off => void' )
        
Last reviewed on Tue Oct 04 2022
Read article

Angular - Define animations and attach to an HTML template

Define animations and attach to an HTML template link

Animations are defined in the metadata of the component that controls the HTML element to be animated.

Define the animation link

Put the code that defines your animations under the animations: property within the @Component() decorator.

src/app/open-close.component.ts
      
      @Component({
  selector: 'app-open-close',
  animations: [
    trigger('openClose', [
      // ...
      state('open', style({
        height: '200px',
        opacity: 1,
        backgroundColor: 'yellow'
      })),
      state('closed', style({
        height: '100px',
        opacity: 0.8,
        backgroundColor: 'blue'
      })),
      transition('open => closed', [
        animate('1s')
      ]),
      transition('closed => open', [
        animate('0.5s')
      ]),
    ]),
  ],
  templateUrl: 'open-close.component.html',
  styleUrls: ['open-close.component.css']
})
export class OpenCloseComponent {
  isOpen = true;

  toggle() {
    this.isOpen = !this.isOpen;
  }

}
    

When an animation trigger for a component is defined, attach it to an element in the template. Wrap the trigger name in brackets and precede it with an @ symbol. Bind the trigger to a template expression using standard Angular property binding syntax. The triggerName is the name of the trigger, and expression evaluates to a defined animation state.

      
      <div [@triggerName]="expression">…</div>;
    

The animation is executed or triggered when the expression value changes to a new state.

The following code snippet binds the trigger to the value of the isOpen property.

src/app/open-close.component.html
      
      <nav>
  <button type="button" (click)="toggle()">Toggle Open/Close</button>
</nav>

<div [@openClose]="isOpen ? 'open' : 'closed'" class="open-close-container">
  <p>The box is now {{ isOpen ? 'Open' : 'Closed' }}!</p>
</div>
    

In this example, when the isOpen expression evaluates to a defined state of open or closed , it notifies the trigger openClose of a state change. Then it's up to the openClose code to handle the state change and kick off a state change animation.

For elements entering or leaving a page (inserted or removed from the DOM), you can make the animations conditional. For example, use *ngIf with the animation trigger in the HTML template.

NOTE :
In the component file, set the trigger that defines the animations as the value of the animations: property in the @Component() decorator.

Attach an animation to an HTML template link

In the HTML template file, use the trigger name to attach the defined animations to the HTML element to be animated.

Last reviewed on Fri Oct 28 2022
Read article

Angular - Introduction to Angular animations

Introduction to Angular animations link

Animation provides the illusion of motion: HTML elements change styling over time. Well-designed animations can make your application more fun and straightforward to use, but they aren't just cosmetic. Animations can improve your application and user experience in a number of ways:

  • Without animations, web page transitions can seem abrupt and jarring
  • Motion greatly enhances the user experience, so animations give users a chance to detect the application's response to their actions
  • Good animations intuitively call the user's attention to where it is needed

Typically, animations involve multiple style transformations over time. An HTML element can move, change color, grow or shrink, fade, or slide off the page. These changes can occur simultaneously or sequentially. You can control the timing of each transformation.

Angular's animation system is built on CSS functionality, which means you can animate any property that the browser considers animatable. This includes positions, sizes, transforms, colors, borders, and more. The W3C maintains a list of animatable properties on its CSS Transitions page.

About this guide link

This guide covers the basic Angular animation features to get you started on adding Angular animations to your project.

The features described in this guide —and the more advanced features described in the related Angular animations guides— are demonstrated in an example application available as a live example / download example .

Prerequisites link

The guide assumes that you're familiar with building basic Angular apps, as described in the following sections:

  • Tutorial
  • Architecture Overview

Getting started link

The main Angular modules for animations are @angular/animations and @angular/platform-browser . When you create a new project using the CLI, these dependencies are automatically added to your project.

To get started with adding Angular animations to your project, import the animation-specific modules along with standard Angular functionality.

Step 1: Enabling the animations module link

Import BrowserAnimationsModule , which introduces the animation capabilities into your Angular root application module.

src/app/app.module.ts
      
      import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

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

NOTE :
When you use the CLI to create your app, the root application module app.module.ts is placed in the src/app folder.

Step 2: Importing animation functions into component files link

If you plan to use specific animation functions in component files, import those functions from @angular/animations .

src/app/app.component.ts
      
      import { Component, HostBinding } from '@angular/core';
import {
  trigger,
  state,
  style,
  animate,
  transition,
  // ...
} from '@angular/animations';
    

NOTE :
See a summary of available animation functions at the end of this guide.

Step 3: Adding the animation metadata property link

In the component file, add a metadata property called animations: within the @Component() decorator. You put the trigger that defines an animation within the animations metadata property.

src/app/app.component.ts
      
      @Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.css'],
  animations: [
    // animation triggers go here
  ]
})
    

Animating a transition link

Let's animate a transition that changes a single HTML element from one state to another. For example, you can specify that a button displays either Open or Closed based on the user's last action. When the button is in the open state, it's visible and yellow. When it's the closed state, it's translucent and blue.

In HTML, these attributes are set using ordinary CSS styles such as color and opacity. In Angular, use the style() function to specify a set of CSS styles for use with animations. Collect a set of styles in an animation state, and give the state a name, such as open or closed .

Let's create a new open-close component to animate with simple transitions.

Run the following command in terminal to generate the component:

      
      ng g component open-close
    

This will create the component at src/app/open-close.component.ts .

Animation state and styles link

Use Angular's state() function to define different states to call at the end of each transition. This function takes two arguments: A unique name like open or closed and a style() function.

Use the style() function to define a set of styles to associate with a given state name. You must use camelCase for style attributes that contain dashes, such as backgroundColor or wrap them in quotes, such as 'background-color' .

Let's see how Angular's state() function works with the style⁣­(⁠) function to set CSS style attributes. In this code snippet, multiple style attributes are set at the same time for the state. In the open state, the button has a height of 200 pixels, an opacity of 1, and a yellow background color.

src/app/open-close.component.ts
      
      // ...
state('open', style({
  height: '200px',
  opacity: 1,
  backgroundColor: 'yellow'
})),
    

In the following closed state, the button has a height of 100 pixels, an opacity of 0.8, and a background color of blue.

src/app/open-close.component.ts
      
      state('closed', style({
  height: '100px',
  opacity: 0.8,
  backgroundColor: 'blue'
})),
    

Transitions and timing link

In Angular, you can set multiple styles without any animation. However, without further refinement, the button instantly transforms with no fade, no shrinkage, or other visible indicator that a change is occurring.

To make the change less abrupt, you need to define an animation transition to specify the changes that occur between one state and another over a period of time. The transition() function accepts two arguments: The first argument accepts an expression that defines the direction between two transition states, and the second argument accepts one or a series of animate() steps.

Use the animate() function to define the length, delay, and easing of a transition, and to designate the style function for defining styles while transitions are taking place. Use the animate() function to define the keyframes() function for multi-step animations. These definitions are placed in the second argument of the animate() function.

Animation metadata: duration, delay, and easing link

The animate() function (second argument of the transition function) accepts the timings and styles input parameters.

The timings parameter takes either a number or a string defined in three parts.

      
      animate (duration)
    

or

      
      animate ('duration delay easing')
    

The first part, duration , is required. The duration can be expressed in milliseconds as a number without quotes, or in seconds with quotes and a time specifier. For example, a duration of a tenth of a second can be expressed as follows:

  • As a plain number, in milliseconds: 100

  • In a string, as milliseconds: '100ms'

  • In a string, as seconds: '0.1s'

The second argument, delay , has the same syntax as duration . For example:

  • Wait for 100ms and then run for 200ms: '0.2s 100ms'

The third argument, easing , controls how the animation accelerates and decelerates during its runtime. For example, ease-in causes the animation to begin slowly, and to pick up speed as it progresses.

  • Wait for 100ms, run for 200ms. Use a deceleration curve to start out fast and slowly decelerate to a resting point: '0.2s 100ms ease-out'

  • Run for 200ms, with no delay. Use a standard curve to start slow, accelerate in the middle, and then decelerate slowly at the end: '0.2s ease-in-out'

  • Start immediately, run for 200ms. Use an acceleration curve to start slow and end at full velocity: '0.2s ease-in'

NOTE :
See the Material Design website's topic on Natural easing curves for general information on easing curves.

This example provides a state transition from open to closed with a 1-second transition between states.

src/app/open-close.component.ts
      
      transition('open => closed', [
  animate('1s')
]),
    

In the preceding code snippet, the => operator indicates unidirectional transitions, and <=> is bidirectional. Within the transition, animate() specifies how long the transition takes. In this case, the state change from open to closed takes 1 second, expressed here as 1s .

This example adds a state transition from the closed state to the open state with a 0.5-second transition animation arc.

src/app/open-close.component.ts
      
      transition('closed => open', [
  animate('0.5s')
]),
    

NOTE :
Some additional notes on using styles within state and transition functions.

  • Use state() to define styles that are applied at the end of each transition, they persist after the animation completes

  • Use transition() to define intermediate styles, which create the illusion of motion during the animation

  • When animations are disabled, transition() styles can be skipped, but state() styles can't

  • Include multiple state pairs within the same transition() argument:

          
          transition( 'on => off, off => void' )
        

Triggering the animation link

An animation requires a trigger , so that it knows when to start. The trigger() function collects the states and transitions, and gives the animation a name, so that you can attach it to the triggering element in the HTML template.

The trigger() function describes the property name to watch for changes. When a change occurs, the trigger initiates the actions included in its definition. These actions can be transitions or other functions, as we'll see later on.

In this example, we'll name the trigger openClose , and attach it to the button element. The trigger describes the open and closed states, and the timings for the two transitions.

NOTE :
Within each trigger() function call, an element can only be in one state at any given time. However, it's possible for multiple triggers to be active at once.

Defining animations and attaching them to the HTML template link

Animations are defined in the metadata of the component that controls the HTML element to be animated. Put the code that defines your animations under the animations: property within the @Component() decorator.

src/app/open-close.component.ts
      
      @Component({
  selector: 'app-open-close',
  animations: [
    trigger('openClose', [
      // ...
      state('open', style({
        height: '200px',
        opacity: 1,
        backgroundColor: 'yellow'
      })),
      state('closed', style({
        height: '100px',
        opacity: 0.8,
        backgroundColor: 'blue'
      })),
      transition('open => closed', [
        animate('1s')
      ]),
      transition('closed => open', [
        animate('0.5s')
      ]),
    ]),
  ],
  templateUrl: 'open-close.component.html',
  styleUrls: ['open-close.component.css']
})
export class OpenCloseComponent {
  isOpen = true;

  toggle() {
    this.isOpen = !this.isOpen;
  }

}
    

When you've defined an animation trigger for a component, attach it to an element in that component's template by wrapping the trigger name in brackets and preceding it with an @ symbol. Then, you can bind the trigger to a template expression using standard Angular property binding syntax as shown below, where triggerName is the name of the trigger, and expression evaluates to a defined animation state.

      
      <div [@triggerName]="expression">…</div>;
    

The animation is executed or triggered when the expression value changes to a new state.

The following code snippet binds the trigger to the value of the isOpen property.

src/app/open-close.component.html
      
      <nav>
  <button type="button" (click)="toggle()">Toggle Open/Close</button>
</nav>

<div [@openClose]="isOpen ? 'open' : 'closed'" class="open-close-container">
  <p>The box is now {{ isOpen ? 'Open' : 'Closed' }}!</p>
</div>
    

In this example, when the isOpen expression evaluates to a defined state of open or closed , it notifies the trigger openClose of a state change. Then it's up to the openClose code to handle the state change and kick off a state change animation.

For elements entering or leaving a page (inserted or removed from the DOM), you can make the animations conditional. For example, use *ngIf with the animation trigger in the HTML template.

NOTE :
In the component file, set the trigger that defines the animations as the value of the animations: property in the @Component() decorator.

In the HTML template file, use the trigger name to attach the defined animations to the HTML element to be animated.

Code review link

Here are the code files discussed in the transition example.

      
      @Component({
  selector: 'app-open-close',
  animations: [
    trigger('openClose', [
      // ...
      state('open', style({
        height: '200px',
        opacity: 1,
        backgroundColor: 'yellow'
      })),
      state('closed', style({
        height: '100px',
        opacity: 0.8,
        backgroundColor: 'blue'
      })),
      transition('open => closed', [
        animate('1s')
      ]),
      transition('closed => open', [
        animate('0.5s')
      ]),
    ]),
  ],
  templateUrl: 'open-close.component.html',
  styleUrls: ['open-close.component.css']
})
export class OpenCloseComponent {
  isOpen = true;

  toggle() {
    this.isOpen = !this.isOpen;
  }

}
    

Summary link

You learned to add animation to a transition between two states, using style() and state() along with animate() for the timing.

Learn about more advanced features in Angular animations under the Animation section, beginning with advanced techniques in transition and triggers.

Animations API summary link

The functional API provided by the @angular/animations module provides a domain-specific language (DSL) for creating and controlling animations in Angular applications. See the API reference for a complete listing and syntax details of the core functions and related data structures.

Function name What it does
trigger() Kicks off the animation and serves as a container for all other animation function calls. HTML template binds to triggerName . Use the first argument to declare a unique trigger name. Uses array syntax.
style() Defines one or more CSS styles to use in animations. Controls the visual appearance of HTML elements during animations. Uses object syntax.
state() Creates a named set of CSS styles that should be applied on successful transition to a given state. The state can then be referenced by name within other animation functions.
animate() Specifies the timing information for a transition. Optional values for delay and easing . Can contain style() calls within.
transition() Defines the animation sequence between two named states. Uses array syntax.
keyframes() Allows a sequential change between styles within a specified time interval. Use within animate() . Can include multiple style() calls within each keyframe() . Uses array syntax.
group() Specifies a group of animation steps ( inner animations ) to be run in parallel. Animation continues only after all inner animation steps have completed. Used within sequence() or transition() .
query() Finds one or more inner HTML elements within the current element.
sequence() Specifies a list of animation steps that are run sequentially, one by one.
stagger() Staggers the starting time for animations for multiple elements.
animation() Produces a reusable animation that can be invoked from elsewhere. Used together with useAnimation() .
useAnimation() Activates a reusable animation. Used with animation() .
animateChild() Allows animations on child components to be run within the same timeframe as the parent.

More on Angular animations link

You might also be interested in the following:

  • Transition and triggers
  • Complex animation sequences
  • Reusable animations
  • Route transition animations

Check out this presentation, shown at the AngularConnect conference in November 2017, and the accompanying source code.

Last reviewed on Mon Feb 28 2022
Read article