How to Implement Click Event Handling and Animation Effects in Angular 4

Every time I click on an item in the accordion list, all items expand. Is there a way to only open the card whose header was clicked?

check out this plnkr example

app.component.html

        <div id="accordion" *ngIf="res">
            <div class="card" *ngFor="let r of res;let i=index">
                <div class="card-header">
                    <h5 class="mb-0">
                        <button class="btn btn-link" 
                        (click)="toggleShowDiv(i)">
                            Collapsible Group Item #1
                        </button>
                    </h5>
                </div>

                <div id="a{{i}}" [@slideInOut]="animationState">
                    <div class="card-body">
                        <div class="table-responsive">
                            <table class="table">
                               dnf ksdfkg skdfgk sd mkdfdm
                               d kmfsd mdksm dk mdf
                               d kdm kd kdsmfk sd
                                sdfsdkg sdkm gdkg dk
                            </table>
                        </div>
                    </div>
                </div>
            </div>
        </div>

app.component.ts

import { Component, OnInit, ElementRef } from '@angular/core';
import { SlideInOutAnimation } from './animation';

@Component({
selector: 'my-app',
templateUrl: './app.component.html',
animations: [SlideInOutAnimation]
})

export class AppComponent implements OnInit {
res = [1, 2, 3, 4];
animationState = 'out';
constructor(private el: ElementRef) {}
ngOnInit() {

}
toggleShowDiv(id) {
    this.animationState = this.animationState === 'out' ? 'in' : 
 'out';
  }
}

Is it possible to add animation to the card body when it is clicked for expansion?

Answer №1

The issue lies in the fact that all four elements in the list are being generated using a *ngFor loop, and the same click action is applied to all of them simultaneously. The correct approach is to correctly retrieve the id of the collapsible element and apply the animation only to that specific element.

Below is a proposed solution:

app.component.ts

import { Component, OnInit, ElementRef } from '@angular/core';
import { SlideInOutAnimation } from './animation';

@Component({
    selector: 'my-app',
    templateUrl: './app.component.html',
    animations: [SlideInOutAnimation]
})

export class AppComponent implements OnInit {

    modelsList: { id: number, header: string, text: string, animationState: string }[] = [
        { "id": 0, "header": "Some header", "text": "Some text", "animationState": "out" },
        { "id": 1, "header": "Some header", "text": "Some text", "animationState": "out" },
        { "id": 2, "header": "Some header", "text": "Some text", "animationState": "out" },
        { "id": 3, "header": "Some header", "text": "Some text", "animationState": "out" }
    ]; 

    constructor(private el: ElementRef) {}
    ngOnInit() {

    }
    toggleShowDiv(id) {
        this.modelsList[id].animationState = this.modelsList[id].animationState === "out" ? 'in' : "out";
      }
      objectKeys(obj) {
        return Object.keys(obj);
    }
}

app.component.html

<div class="container">
 <div class="row">
    <div class="col">
        <div id="accordion" *ngIf="modelsList">
            <div class="card" *ngFor="let key of objectKeys(modelsList); let i=index" >
                <div class="card-header">
                    <h5 class="mb-0">
                        <button class="btn btn-link" (click)="toggleShowDiv(i)">
                                {{modelsList[i].header}}
                        </button>
                    </h5>
                </div>

                <div id="a{{i}}" [@slideInOut]="modelsList[i].animationState">
                    <div class="card-body">
                        <div class="table-responsive">
                            <table class="table">
                                   {{modelsList[i].text}}
                            </table>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
 </div>
</div>

The content and headers of the accordion list have been relocated to the TS code for easier application of element-specific operations. There may be alternative approaches to achieve this directly in HTML, but I have not explored those possibilities yet.

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

Error: It is not permitted to have multiple instances of the CORS header 'Access-Control-Allow-Origin', nor is it allowed to have the header missing

Having trouble with CORS headers when making an HTTP request from my Angular 7 app (hosted on http://localhost:4200) to my Spring-Boot app (hosted on https://localhost:8924) using Firefox. The Spring-Boot app has a CORS filter that is applied to the reque ...

The function signature '() => void' cannot be assigned to a variable of type 'string'

Encountering an issue in Typescript where I am attempting to comprehend the declaration of src={close} inside ItemProps{}. The error message received reads: Type '() => void' is not assignable to type 'string'. Regrettably, I am ...

Is your Angular2 form page experiencing reloading issues?

I am currently incorporating Angular2 into my project. I am facing an issue where the page keeps refreshing, and I'm unable to determine the cause. Below is a snippet of my form: <form> <div class="form-group"> ...

Authenticate users into an Angular application using AD FS and Saml directly, eliminating the need for third-party services like auth0 or OpenId Connect

Looking to meet business requirements using Spring Boot, Angular 8, and AD FS login with Saml. We are currently in the process of developing an application that requires login authentication with AD FS using the SAML protocol. I am seeking clarification ...

Steer clear of receiving null values from asynchronous requests running in the background

When a user logs in, I have a request that retrieves a large dataset which takes around 15 seconds to return. My goal is to make this request upon login so that when the user navigates to the page where this data is loaded, they can either see it instantly ...

Finding the topOffset in Angular by targeting a class called 'dropdown'

I am trying to achieve the same result in Angular as I do with jQuery/HTML. When using jQuery, the topOffset value remains the same whether I scroll or not. // get the top offset of the dropdown (distance from top of the page) var topOffset = $(".drop ...

Developing a dynamic object in Typescript to structure and optimize API responses

Currently Working Explanation: This is similar to the data array received from the API response responseBarDataStacked = [ { sku: "Data 1", month: "Jun", value: 20 }, { sku: "Data 2", month: "Jun", value: 25 ...

Changing the names of the remaining variables while object destructuring in TypeScript

UPDATE: I have created an issue regarding this topic on github: https://github.com/Microsoft/TypeScript/issues/21265 It appears that the syntax { ...other: xother } is not valid in JavaScript or TypeScript, and should not compile. Initial Query: C ...

Error encountered during conversion to Typescript for select event and default value

When trying to set the defaultValue in a Select component, TSlint throws an error - Type 'string' is not assignable to type 'ChangeEvent<HTMLInputElement> | undefined - for the code snippet below: const App = () => { const [ mont ...

Detecting activity and keeping idle ng alive

I am utilizing angular ng-idle (core and keepalive) in my project, with the goal of detecting user activity. Despite my efforts to search for documentation on when each ng-idle event occurs, I have come up empty-handed. While I have found examples of h ...

What is the best way to incorporate a Vue single file component into a Typescript-infused view?

Despite trying numerous methods, I consistently encounter build or runtime errors. To my surprise, I have not come across a functional example or post related to this inquiry after extensive research. I initiated a new project with Typescript using the Vue ...

Encountered an error while trying to install a package using NPM due to the requirement of 'require-from-string@

Every time I try to install a package (even nodejs), I encounter this issue. Here is what I have tried so far: Uninstalled all dependencies Cleared cache Reinstalled NPM / AngularCli Unfortunately, running any NPM command still results in the same error ...

Exploring the integration of traditional service methodologies into modern Angular applications

I am tasked with converting various types of services like SOAP-based services, WCF XML services, and web services that are currently running in a Silverlight app. For this conversion, we plan to use Angular as the front end while keeping the server side u ...

You need to provide 1 type argument(s) for the Generic type ModuleWithProviders<T> in Angular 10 Swagger Codegen

Currently, I am generating Codegen proxies using . Upon implementing this in Angular 10, I encountered the following error. How can this issue be resolved? The error message reads: 'Generic type 'ModuleWithProviders' requires 1 type argume ...

I am encountering an issue in Vue3 where the parent event handler arguments are not being typed with the child's defineEmits definition. Can anyone explain this to me

I am struggling to correctly type the parent event handler based on the child definition, but no matter what I try, I always end up with `any` as the event type. Here is a code example: <script setup lang="ts"> // Child component type Even ...

Guide on importing and using types from an external library in my declaration file

Querying Library Types in a .d.ts Declaration File I am currently working on creating a custom namespace in a cf.d.ts file to define general-purpose types for my application. This allows me to avoid importing modules repeatedly whenever I need to referenc ...

Delete the text in MUI's TablePagination component that displays the number of rows per page and the total rows in the table

Currently, I am integrating MUI's tablePagination component into my React table with TypeScript. I am looking to remove/disable the circlemarked text displayed in the image (the picture is an example from MUI). https://i.stack.imgur.com/ib0t2.png Af ...

Encountering issues while trying to update npm in a Angular 6 project

Attempting to upgrade npm from version 6.1.0 to 6.4.0 using the command line interface: npm install -g npm Unfortunately, encountered an error during the update process. npm ERR! path /usr/local/lib/node_modules/npm/node_modules/ansi-regex npm ERR! co ...

Identifying when an element is in or out of view using Next.js and TypeScript

I'm currently working on an app using Next and Typescript. The app features a navigation bar at the top of the screen, and I need it to change its style once it reaches a certain point in the view. I attempted to use jQuery for this purpose, but encou ...

Navigating through pages: How can I retrieve the current page value for implementing next and previous functions in Angular 7?

Greetings, I am a new learner of Angular and currently working on custom pagination. However, I am facing difficulty in finding the current page for implementing the next and previous functions. Can anyone guide me on how to obtain the current page value? ...