An easy way to add animation to the :host element when it exits using Angular 12's animation features

If you are looking to create a simple fade in and out effect for a component using Angular, you can achieve this by utilizing the :enter and :leave events:

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

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.scss'],
  animations: [
    trigger('host', [
      transition(':enter', [
        style({ opacity: 0 }),
        animate('240ms linear', style({ opacity: 1 })),
      ]),
      transition(':leave', [
        style({ opacity: 1 }),
        animate('240ms linear', style({ opacity: 0 })),
      ])
    ]),
  ]
})

export class TestComponent {
  @HostBinding('@host') host() {
    return true;
  }
}

To use the component with the fade effect, include it in your HTML like this:

<app-test *ngIf="someBoolean"></app-test>

The animation should work properly on entering the component. However, if the element is not fading out when the component is being removed (when someBoolean is set to false), it may be due to a missing piece of code or configuration.

If the fade-out effect is not working as expected, you may need to troubleshoot and determine what is causing the issue.

Answer №1

Utilizing *ngIf within the parent component can cause the element animations to go unnoticed

Let's explore what occurs in this scenario

  • someBoolean => initialized as false
  • <app-test *ngIf='someBoolean'></app-test>
    does not exist
  • someBoolean => now set to true
  • Load
    <app-test></app-test>
  • Initiate animations; ... Pause for a moment, did we just load app-test before starting the animations? The timing of when animations are triggered is crucial. This is why your animations may not be working - they need to be registered first

So let's halt the aforementioned sequence and try a different approach

  • someBoolean => initialized as false
  • <app-test [shown]='someBoolean'></app-test>
    is created
  • Register Animations
  • someBoolean => now set to true
  • Show contents of
    <app-test></app-test>
  • Animations kick in after being properly registered!

Now that we understand the process, let's delve into the code implementation

Component Usage

`<app-test [shown]='someBoolean'></app-test>`

Component TypeScript File

@Component({
  selector: "app-test",
  templateUrl: "./test.component.html",
  styleUrls: ["./test.component.css"],
  animations: [
    trigger("host", [
      transition(":enter", [
        style({ opacity: 0 }),
        animate("240ms linear", style({ opacity: 1 }))
      ]),
      transition(":leave", [
        style({ opacity: 1 }),
        animate("240ms linear", style({ opacity: 0 }))
      ])
    ])
  ]
})
export class TestComponent implements OnInit {
  // @HostBinding("@host") host() {
  //   return true;
  // }
  @Input() shown;

  constructor() {}

  ngOnInit() {}
}

I have omitted @HostBinding since its implementation was unclear.

Lastly, apply *ngIf within the component content itself

<div *ngIf='shown'>
  <!-- Animation in action! -->
</div>

Check out Demo Here

Answer №2

Is this the solution to your problem?

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

@Component({
  selector: 'container',
  animations: [
    trigger('toggleAnimation', [
      state('open', style({ overflow: 'hidden', opacity: '*' })),
      state('closed', style({ overflow: 'hidden', opacity: 0, height: 0 })),
      transition('open => closed', animate('400ms ease-in-out')),
      transition('closed => open', animate('400ms ease-in-out')),
    ]),
  ],
  template: `
    <button (click)="toggleState()">TOGGLE</button>
    <div [@toggleAnimation]="animationState">
      <app-child-component></app-child-component>
    </div>
  `,
})
export class ContainerComponent {
  animationState = 'closed';

  toggleState() {
    this.animationState = this.animationState === 'open' ? 'closed' : 'open';
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Sorting elements with a custom selector using Angular's ViewChild

Currently, I am delving into the realm of angular ViewChild. However, I find myself facing a roadblock when attempting to utilize ViewChild in selecting custom reference variables from the DOM. Within my template lie two tables: <mat-table #eventTable ...

Angular Material Cards do not expand to fill the entire row

I recently started using Angular Material and I'm attempting to create a page with cards containing photos. However, it seems that by default, the mat-cards stack vertically and do not fill out the space in the row to the right. I've experimented ...

Postman is having trouble communicating with an express router and is unable to send requests

Currently, I am experiencing some challenges while trying to grasp the concepts of express and node with typescript, particularly when setting up a router. In my bookRoutes.ts file, I have defined my router in the following manner: import express, { Expre ...

Angular button not functioning properly with disabled attribute

I have been experimenting with both [disabled] or disabled but it doesn't seem to be working according to my TypeScript conditions. There are 4 buttons that I need to disable based on various TypeScript conditions. I have a total of 7 conditions that ...

Error message: "Error encountered while building Next.js - ReferenceError: 'describe' is not defined"

I am facing difficulties achieving a successful next build without encountering the following error: > Build error occurred { ReferenceError: describe is not defined Although the dev server and tests execute smoothly, it appears that the jest global d ...

Implementing a scroll-triggered class addition in Angular

I am currently refreshing my knowledge of Angular. After installing AngularCLI, I am attempting to transition from using jQuery to add a class on scroll. Would it be necessary to utilize [ngClass] in order to check a variable with window location? Right ...

Showing the contents of an array which contains arrays

Retrieves the elements stored in the history array. Each element of the history array is a separate array containing fields with names and values. The goal is to display this history table by iterating over each element of the array and displaying it in ...

How to open a print preview in a new tab using Angular 4

Currently, I am attempting to implement print functionality in Angular 4. My goal is to have the print preview automatically open in a new tab along with the print popup window. I'm struggling to find a way to pass data from the parent window to the c ...

Adding client-side scripts to a web page in a Node.js environment

Currently, I am embarking on a project involving ts, node, and express. My primary query is whether there exists a method to incorporate typescript files into HTML/ejs that can be executed on the client side (allowing access to document e.t.c., similar to ...

I am unable to showcase the image at this time

Hey there, I'm having an issue with displaying an image stored inside the NextJS API folder. The alt attribute is showing up fine, but the actual image isn't displaying. When I console.log the image data, everything seems to be in place. Can anyo ...

Establish a function within an interface using the name obtained from a constant in Typescript

How can I define functions within an interface using constants as function names? I have a const array containing event names and I want to create an ServerToClientEvents interface for SocketIO. I can define a function like this and it will work: interfac ...

Do parallel awaits in JS/TS work only on Chrome browsers exclusively?

Encountering a strange issue with promise resolution behavior in JS/TS. Using Node LTS. It seems that the difference lies in whether the promise resolves to a value that is later read in the code or if it's simply fire-and-forget (void response type). ...

Resolving typescript error in my custom hook

Implementing this ResizeObserver hook in my project using typescript const useResizeObserver = () => { const [entry, setEntry] = useState<ResizeObserverEntry>(); const [node, setNode] = useState<Element | null>(null); const observer = ...

Presenting two arrays simultaneously creates angular duplicates

Encountering an issue while trying to display two arrays containing channel information: List of channels List of subscriptions that users have opted for. channels = [ { "id": 1, "name": "arte", "service&q ...

Issue with Angular 2: Route guard failing to work after browser refresh

Defining these routes in app.module.ts: ... { path: 'mypath', component: MyComponent, canActivate: [RouteGuard] }, { path: '', redirectTo: '/home', pathMatch: 'full' }, { path: '**', redirectTo: '/ho ...

The combination of ASP.Net Core 1.1 and Angular 2 in a PUT request triggers a No Access Control

In my ASP.Net Core 1.1 backend, CORS has been enabled as shown below: public void ConfigureServices(IServiceCollection services) { // Add framework services. services.AddDbContext<WebAPIDataContext>(options => { options.UseMyS ...

Adding a file to the model.module.ts registration process

After diving into an Angular 6 book and grasping the concept of registering classes, there's this particular syntax highlighted in the image below that threw me off. Can anyone shed some light on why it's different and explain it to me? I even tr ...

How to implement Dragula and Angular to enable draggable elements to be dropped in any position within their container?

I am in the process of developing a web application using Angular, which incorporates dragula. While the current drag and drop functionality works well for moving items within a designated "bag", I am seeking to enhance it with more advanced features. Is ...

Is zone.js responsible for the issue of CSS not being rendered properly?

My print preview CSS is functioning properly in my current location after testing it on various browsers and computers. However, when accessed from a location in Japan, the CSS does not seem to work correctly, specifically affecting the <table>. Use ...

Google Cloud PubSub does not automatically resend unacknowledged messages

The answer chosen for this particular question contains some pertinent details I currently have a subscription set up with the following parameters: https://i.stack.imgur.com/Bn0d4.png along with the following code snippet: const subscription = this.pub ...