Issue with Angular Animation not functioning properly when used with a Child component that utilizes Input and

I have been struggling with an issue that I couldn't resolve even after consulting the Angular documentation and various tutorials. The problem lies in my child component accordeon, which is utilized in multiple others. Within the accordeon, it receives a boolean value from the parent component to determine whether it should be open or closed. Additionally, the accordeon consists of two ng-content sections - one for the title provided by the parent component and another for the content.

Here is the HTML code snippet for the accordeon:

<div class="d-flex jc-between ai-center p-s" (click)="toggleAccordeon();" [ngClass]="specialAccordeon ? 'accordeon' : 'special-accordeon'">
  <ng-content select="[slot=title]"></ng-content>
  <span class="icon-chevron_bottom" [ngClass]="accordeonOpened ? 'rotation_180' : ''"></span>
</div>
<ng-content [@openCloseAccordeon]=animateAccordeon select="[slot=content]" [ngStyle]="accordeonOpened && {'display': 'none'}"></ng-content>

The corresponding .ts file for accordeon:

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

@Component({
  selector: 'srp-accordeon',
  templateUrl: './accordeon.component.html',
  styleUrls: ['./accordeon.component.scss'],
  animations: [
    trigger('openCloseAccordeon', [
      state('initial', style({ display: 'none', })),
      state('final', style({ display: 'block', })),
      transition('initial => final', [ animate('1s') ]),
      transition('final => initial', [ animate('2s') ]),
    ]),
  ]
})
export class AccordeonComponent implements OnInit {

  accordeonOpened = false;
  animateAccordeon = 'initial';
  @Output() open: EventEmitter<any> = new EventEmitter();
  @Output() close: EventEmitter<any> = new EventEmitter();
  @Output() openAccordeon: EventEmitter<any> = new EventEmitter();
  @Output() closeAccordeon: EventEmitter<any> = new EventEmitter();

  @Input() specialAccordeon;

  public toggleAccordeon(): void {
    this.animateAccordeon = this.animateAccordeon === 'initial' ? 'final' : 'initial';
    this.accordeonOpened = !this.accordeonOpened;
    if (this.accordeonOpened) {
      this.open.emit(true);
    } else {
      this.close.emit(false);
    }
    if (this.animateAccordeon === 'initial') {
      this.closeAccordeon.emit('initial');
    } else {
      this.openAccordeon.emit('final');
    }
  }

  constructor() { }

  ngOnInit() {
  }

}

With regards to the parent component order-delivery, here is the relevant part of the HTML:

Although I have managed to control the opening and closing behavior using ng-class, integrating [@openCloseAccordeon]=animateAccordeon has not been successful.

<srp-accordeon [specialAccordeon]="true" (close)="accordeonOpened = false" (open)="accordeonOpened = true" (closeAccordeon)="animateAccordeon = 'initial'" (openAccordeon)="animateAccordeon = 'final'">
    <ng-container slot="title">{{currentOrder.statusLabel}} {{(!currentOrder.isCanceled ? currentOrder.isDeliveryAtHome ? 'order.atHome' : 'order.inWithdrawalPoint' : string.Empty) | translate}}</ng-container>
    <ng-container slot="content">
        <div class="order-delivery__details mb-s" [ngClass]="accordeonOpened ? 'accordeon-opened' : 'accordeon-closed'">

In conclusion, I am trying to trigger the animation upon user interaction with the . It seems like I might be missing a crucial piece of data to pass from the order-delivery component to the accordeon, but I can't quite figure out what that is.

Any assistance you can provide would be greatly appreciated. Thank you.

Answer №1

After much exploration, I finally discover the solution.

accordeon.html:

<div class="d-flex jc-between ai-center p-s" (click)="toggleAccordeon(); toggleAnimation();" [ngClass]="specialAccordeon ? 'accordeon' : 'special-accordeon'">
  <ng-content select="[slot=title]"></ng-content>
  <span class="icon-chevron_bottom" [ngClass]="accordeonOpened ? 'rotation_180' : ''"></span>
</div>
<div [@openCloseAccordeon]=animateAccordeon>
  <ng-content select="[slot=content]"></ng-content>
</div>

accordeon.ts:

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

@Component({
  selector: 'srp-accordeon',
  templateUrl: './accordeon.component.html',
  styleUrls: ['./accordeon.component.scss'],
  animations: [
    trigger('openCloseAccordeon', [
      state('initial', style({
        opacity: '0',
      })),
      state('final', style({
        opacity: '1',
      })),
      transition('initial => final', [
        animate('1s')
      ]),
      transition('final => initial', [
        animate('2s')
      ]),
    ]),
  ]
})
export class AccordeonComponent implements OnInit {

  accordeonOpened = false;
  animateAccordeon = 'initial';

  @Output() open: EventEmitter<any> = new EventEmitter();
  @Output() close: EventEmitter<any> = new EventEmitter();

  @Input() specialAccordeon;

  public toggleAccordeon(): void {
    this.accordeonOpened = !this.accordeonOpened;
    if (this.accordeonOpened) {
      this.open.emit(true);
    } else {
      this.close.emit(false);
    }
  }

  public toggleAnimation() {
    this.animateAccordeon = this.animateAccordeon === 'initial' ? 'final' : 'initial';
  }

  constructor() { }

  ngOnInit() {
  }
}

No specific details needed in the parent component. One important note: the animation won't work directly on ng-content, so a wrapping div is necessary.

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

How can I troubleshoot the 'mdDialog console error' that says 'cannot read property element of null'?

Two of my templates are named Left_template_view_html and center_template_view_html When I click on a md-button in the Left_template_view_html I am attempting to display an mdDialog on the document.body What should I pass into the parent parameter: angu ...

Is there a specific explanation as to why ng-repeat-start is not functioning properly even with the most recent version of AngularJS?

Can someone please explain why ng-repeat-start is not functioning properly despite using the most up-to-date AngularJS version? I have included it from the CDN: <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></scr ...

Ways to retrieve a returned value from mongoose

I am attempting to retrieve a value from a mongoose callback function, but I keep encountering an error stating TypeError: #<Object> is not a function. I understand that it may be tricky to achieve this, but the way I am querying the database require ...

Bring in a 3D design using the three.js library

I am currently diving into learning three.js and have been closely following their documentation. However, I seem to be facing an issue when trying to import an object from Blender. Can anyone point out what might be going wrong here? I have set up the s ...

The error thrown is: "Attempting to access the 'authService' property of an undefined object using TypeDi."

In the process of setting up an authentication system, I have created a class called AuthRouter: import { Router } from 'express' import Container, { Service } from 'typedi' import AuthenticationController from './index' @Ser ...

Type of parameter that changes based on certain conditions

I need help with a coding snippet interface IProps { isEdit: boolean; menuOpenId: number | boolean } function useMenuForm({ isEdit, menuOpenId }: IProps){...} Any suggestions on how to set menuOpenId as type number when isEdit is true, otherwise keep ...

Tips for implementing simple custom styling within an Angular application without relying on innerHTML

Seeking advice on the best practices for a specific scenario. I am currently developing a small Angular application where users can input text. I would like to allow them to easily make certain words bold or create links. For example, if they type *whatev ...

I'm facing difficulty in setting up an Angular project through the VS code terminal

After successfully installing Node.js v12.18.2 and npm version v6.14.5, I attempted to create an Angular app using the command prompt. However, when trying to run the same command on the VS code terminal, I encountered the following error: 'ng' ...

The console.log method is not functioning properly in the service

When developing my Angular application, I encountered an issue while creating a service. Here is the code snippet: @Injectable({ providedIn: 'root' }) export class PropertiesNameService { properties: string[] = []; constructor(p ...

Steps to configure caching settings to ensure no caching for the entire site during specific hours, and constant no-cache policy for a particular page

Managing cache for my website has become quite the challenge. Some pages need to be cached during certain hours to improve navigation speed, while others must not be cached during crucial data update times. And to add to the complexity, there are pages tha ...

How can I make either the left or right section remain sticky for a certain period of time?

Can someone help me figure out how to fix a specific section in place temporarily, similar to the example provided below? In the link above, the Apple Watch product stays fixed while the content on the right moves partially, eventually causing the entire ...

Enhancing functions in C# and JavaScript with additional parameters

Having trouble passing a parameter to a function and adding it to the read function in my script. I added a parameter called val to make the function reusable, but unsure how to integrate it into objhandler.read('one'). Here's what I have i ...

Using Vue with Nuxt and Axios for cross-domain POST requests with a proxy

I've been attempting to perform a cross-domain POST request using nuxt and axios this.$axios.$post('https://hooks.zapier.com/hooks/catch/111111/xxxxx/', { name: 'Jose', }) Encountering CORS blocking, I decided to try using nuxt/p ...

Creating a tree structure from a one-dimensional array with the help of dual data tables in JavaScript

I'm struggling to create a tree structure from a flat array using two Mock data tables in JSON. The table should match the unique IDs to determine the hierarchy between them. JSON with Groups DB array example: { "group": [ { "groupName" ...

Tips for navigating a dynamic viewport using scroll movement

Attempting to create a responsive page with two distinct sections at this example link including: Map View Table View Both of these views (table and map divs) need to be responsive without a hard-coded height, so the size of the map div adjusts automatic ...

Dynamic content within an HTML tree format

Data retrieved from the database is currently in the following format upon query execution [(‘Country-1’, ‘state1’), (‘Country-1’, ‘state2’), (‘Country-1’, ‘state3’), (‘Country-2’, ‘state1’), (‘Country-2’, ‘state2’) ...

Can an identification be included in a label element?

My inquiry is as follows: <label for="gender" class="error">Choose</label> I am interested in dynamically adding an id attribute to the above line using jQuery or JavaScript, resulting in the following html: <label for="gender" class="err ...

Troubleshooting JavaScript in Internet Explorer 9

Currently, I am encountering an issue while attempting to debug JavaScript .js files in my Solution using Visual Studio 2010 and IE 9. Despite placing breakpoints in the files, I am unable to debug successfully. I have attempted various troubleshooting ste ...

Finding the Right Method to Update a React Component's State Variable

Within one of my components, I establish a state variable as follows: const [mediaList, setMediaList] = React.useState<Array<Media>>([]); The type Media represents various properties in TypeScript. I provide the user with the capability to mo ...

Organize pairs of strings into a nested array within an array using Angular

Currently, I am working on a project in Angular. In this project, I have a string that contains special characters which I have successfully removed using regular expressions. Now, my goal is to arrange the first two strings within square brackets and the ...