htmlcssangulartypescriptstackblitz

Difficulty implementing accordion effect in Angular project


I am trying an implementation of accordion effect in one of my Angular views. The most basic accordion example you would find over at w3schools. Please take a look at this stackblitz url where I have tried to implement the same, using the same approach I used in my original project.

https://stackblitz.com/edit/stackblitz-starters-v54vdwmj

Nothing is working. What's confusing is that there is no compilation error or runtime errors in the console which really doesn't help at all. Had there been some sort of errors, it would have at least given me a pointer in some direction.

Can you get this accordion on stackblitz working?

Thanks!


Solution

  • A javascript based accordion use generally a css class.

    You has define:

    .panel {
      padding: 0 18px;
      background-color: white;
      display: none;  /<--see that is always display none
      overflow: hidden;
    }
    

    You need add some like

    .active ~ .panel{  //<--when the button have the class "active"
      display:block    // the panel what is "Subsequent-sibling"
    }
    

    Well, another is that your function "accordianUtility" should be only execute one time. So use ngAfterViewInit in your component and remove the "accordianClicked".

    ngAfterViewInit(){
       acordianUtility()
    }
    

    your forked stackblitz

    More. You should avoid add listeners using javascript, why not use some more simple an "Angular event"?

    and your accordianClicked function in component reply the behaivour of the function in your "acordian-utily.ts

    <!--see how pass the html element using template reference variable (the "#bt")-->
    <button #bt (click)="accordianClicked(bt)" class="accordion">Summary</button>
    
    accordianClicked(bt:HTMLElement)
    {
          bt.classList.toggle('active');
          var panel = bt.nextElementSibling as HTMLElement;
          if (panel.style.maxHeight) {
            panel.style.maxHeight = '';
          } else {
            panel.style.maxHeight = panel.scrollHeight + 'px';
          }
    }
    

    NOTE: Really it's better pass to the function the "panel" as argument

    NOTE2: Really I agree with Naren and JSON Derulo, your should use an "angular aproach". in ng-bootstrap you have a library with accordion, or you can use Bootstrap 5