I am making accordion to make a collapsible div using javascript in angular application..
For which if its not getting open on click over the button on Parent One
or any other parent name..
Html:
<div *ngFor="let item of data">
<button class="accordion"> {{item.parentName}} </button>
<div class="panel" *ngFor="let child of item.childProperties">
<p> {{child.propertyName}} </p>
</div>
</div>
Ts:
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
data: any =
[
{
"parentName": "Parent One",
"childProperties":
[
{ "propertyName": "Property One" },
{ "propertyName": "Property Two" }
]
},
{
"parentName": "Parent Two",
"childProperties":
[
{ "propertyName": "Property Three" },
{ "propertyName": "Property Four" },
{ "propertyName": "Property Five" },
]
},
{
"parentName": "Parent Three",
"childProperties":
[
{ "propertyName": "Property Six" },
{ "propertyName": "Property Seven" },
{ "propertyName": "Property Eight" },
]
}
]
ngOnInit() {
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function () {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.maxHeight) {
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + "px";
}
});
}
}
}
Note: As i am new in angular i am making it with javascript way.. So kindly help me to achieve the result using pure angular and typescript..
Working stackblitz https://stackblitz.com/edit/angular-lp3riw
You can see in demo that the parent button are visible but if you click over the button its not getting expanded..
Also listed down working collapsible button below with static values..
How to make a collapsible accordion as like given stackblitz static values using angular and typescript way (Without any third party or jquery)..
Keep your function in ngAfterViewInit
instead of ngOnInit
. See updated stackblitz
The problem is that on ngOnInit the view is not completely painted, and you do not get all the elements on which you want to bind the function.
ngAfterViewInit() {
var acc = document.getElementsByClassName("accordion");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function () {
this.classList.toggle("active");
var panel = this.nextElementSibling;
if (panel.style.maxHeight) {
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + "px";
}
});
}
}
Using angular do it like shown below.
Keep a click function on the button and bind a property isActive
to the corresponding array element. Then show/hide the accordian based on if isActive has value true/false.
<div *ngFor="let item of data;let i = index;">
<button class="accordion" (click)="toggleAccordian($event, i)"> {{item.parentName}} </button>
<div class="panel" *ngFor="let child of item.childProperties" hide="!item.isActive">
<p> {{child.propertyName}} </p>
</div>
</div>
toggleAccordian(event, index) {
var element = event.target;
element.classList.toggle("active");
if(this.data[index].isActive) {
this.data[index].isActive = false;
} else {
this.data[index].isActive = true;
}
var panel = element.nextElementSibling;
if (panel.style.maxHeight) {
panel.style.maxHeight = null;
} else {
panel.style.maxHeight = panel.scrollHeight + "px";
}
}
The Stackblitz update only show the first element in childProperties Item so if u apply the *ngFor on the p tag you will get all the elements of childProperties
<p *ngFor="let child of item.childProperties"> {{child.propertyName}} </p>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With