Search code examples
angulartailwind-cssngfor

NgFor in a Tailwind Accordion


I have been trying to show an array of posts with the tailwind accordion but it is not working as expected. The accordion will show the headings when a post is created but it would not expand to show the post's content. I have also changed the attributes of data-accordion-target to dynamically target the body using the "ngfor: index as i". Also I am not sure where to place the structural directive because it is kind of showing two separate accordions.

<div id="accordion-collapse" data-accordion="collapse">
  <div *ngFor="let post of posts; index as i">
    <h2 id="accordion-collapse-heading-1">
      <button type="button"
        class="flex items-center justify-between w-full p-5 font-medium rtl:text-right text-gray-500 border border-b-0 border-gray-200 rounded-t-xl focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-800 dark:border-gray-700 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800 gap-3"
        attr.data-accordion-target="#accordion-collapse-body-{{i}}" aria-expanded="true"
        attr.aria-controls="accordion-collapse-body-{{i}}">
        <span>{{post.title}}</span>
        <svg data-accordion-icon class="w-3 h-3 rotate-180 shrink-0" aria-hidden="true"
          xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
          <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
            d="M9 5 5 1 1 5" />
        </svg>
      </button>
    </h2>
    <div id="accordion-collapse-body-{{i}}" class="hidden" attr.aria-labelledby="accordion-collapse-heading-{{i}}">
      <div class="p-5 border border-b-0 border-gray-200 dark:border-gray-700 dark:bg-gray-900">
        <p class="mb-2 text-gray-500 dark:text-gray-400">{{post.content}}</p>
      </div>
    </div>
  </div>
</div>

Sample image


Solution

  • Your template seems fine and the accordion works fine for me.

    Did you install and configure the Flowbite js library that is required for the accordion?

    From the Tailwind Angular docs:

    Install Flowbite:

    npm install flowbite
    

    Update your Tailwind config to include Flowbite:

    /** @type {import('tailwindcss').Config} */
    module.exports = {
      content: [
        "./src/**/*.{html,ts}",
        "./node_modules/flowbite/**/*.js" // 1. add this line
      ],
      theme: {
        extend: {},
      },
      plugins: [
        require('flowbite/plugin') // 2. add this line
      ],
    }
    
    

    Init Flowbite in your component:

    import { Component } from '@angular/core';
    import { OnInit } from '@angular/core';
    import { initFlowbite } from 'flowbite';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css']
    })
    export class AppComponent implements OnInit {
      title = 'web-app';
    
      ngOnInit(): void {
        initFlowbite();
      }
    }
    

    Working example on StackBlitz

    Note that I made some small adjustments to the template:

    1. I changed <h2 id="accordion-collapse-heading-1"> to <h2 id="accordion-collapse-heading-{{i}}">.

    2. I added the code below to the button to make sure only the first button has rounded corners at the top (to prevent it from looking like there are separate accordions like you said):

    [ngClass]="i === 0 ? 'rounded-t-xl' : 'rounded-none'"