DEV Community

Cover image for Dynamic Table Creation with Alpine JS
Azrul Azwar
Azrul Azwar

Posted on

Dynamic Table Creation with Alpine JS

This article explores creating dynamic tables using Alpine JS, a lightweight JavaScript framework. We'll break down the process into three sections: header, body, and footer, focusing on both basic and complex scenarios.

Setting Up:

  1. HTML Structure: We begin with a basic HTML element () with the x-data directive attached. This directive binds reactive data to the element.
  2. JavaScript Data: We define an empty JavaScript object (data) outside the HTML to hold our table data.
  3. The initial code is below:

    <div x-data="data">
    </div>
    
    <script>
    let data = {
    }
    </script>
    

    Header

    • We use the thead element for the header.
    • The x-for directive iterates over table.customHeader data, creating rows and columns dynamically.
    • Complex headers can leverage colspan and rowspan attributes (defined in col.attr) to merge cells.
    • Content within each cell is displayed using x-html and bound to the col.title property.
    <thead class="sticky top-0 z-10 text-gray-700 bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
      <template x-for="row in table.customHeader">
        <tr>
            <template x-for="col in row">
                <th class="px-4 font-semibold text-left border-b py-1.5"
                    x-init="col.attr && Object.keys(col.attr).forEach(e => $el.setAttribute(e, col.attr[e]))">
                    <div class="flex items-center justify-center">
                        <span x-html="col.title" class="whitespace-nowrap"></span>
                    </div>
                </th>
            </template>
        </tr>
      </template>
    </thead>
    
    let data = {
      table: {
          customHeader: [
              [
                  { title: 'City', attr: { rowspan: 2 }, class: 'border-r border-t' },
                  { title: 'Clothes', attr: { colspan: 3 }, class: 'border-r border-t' },
                  { title: 'Accessories', attr: { colspan: 2 }, class: 'border-t' }
              ],
              [
                  { title: 'Trousers', class: 'border-r' },
                  { title: 'Skirts', class: 'border-r' },
                  { title: 'Dresses', class: 'border-r' },
                  { title: 'Bracelets', class: 'border-r' },
                  { title: 'Rings' },
              ]
          ],
      }
    }
    

    Body

    • The tbody element holds the table's data rows.
    • We iterate through table.data using x-for.
    • Each row houses cells (<td>) populated with data from corresponding object properties using x-text.
    <tbody>
        <template x-for="(row, idx) in table.data">
            <tr class="border-b dark:border-gray-700">
                <template x-for="(col, icol) in row.columns">
                    <td x-bind:class="{ [col.class]: !!col.class }" class="px-3 border-b border-gray-200">
                        <div x-text="col.text"></div>
                    </td>
                </template>
            </tr>
        </template>
    </tbody>
    

    And this is the data we want to show:

    data: [
        { "city": "Mandalay", "trousers": 79, "skirts": 16, "dresses": 14, "bracelets": 69, "rings": 99 },
        { "city": "George Town", "trousers": 68, "skirts": 24, "dresses": 90, "bracelets": 96, "rings": 48 },
        { "city": "Gent", "trousers": 26, "skirts": 60, "dresses": 67, "bracelets": 5, "rings": 43 },
        { "city": "Mombasa", "trousers": 34, "skirts": 62, "dresses": 18, "bracelets": 75, "rings": 78 },
        { "city": "Lyon", "trousers": 13, "skirts": 33, "dresses": 12, "bracelets": 0, "rings": 17 },
        { "city": "Vancouver", "trousers": 82, "skirts": 91, "dresses": 18, "bracelets": 96, "rings": 72 },
        { "city": "Cairn", "trousers": 64, "skirts": 43, "dresses": 14, "bracelets": 95, "rings": 55 },
    ]
    

    Footer

    • The tfoot element defines the footer.
    • Similar to the header, it uses x-for to iterate through table.customFooter data.
    • However, the footer can display dynamic values by referencing properties within table.footerData using x-html.
    <tfoot class="sticky bg-gray-100 -bottom-1">
        <template x-for="row in table.customFooter">
            <tr>
                <template x-for="col in row">
                    <td class="px-3 border-b border-gray-200"
                        x-init="col.attr && Object.keys(col.attr).forEach(e => $el.setAttribute(e, col.attr[e]))">
                            <div x-html="table.footerData[col.name)">
                            </div>
                    </td>
                </template>
            </tr>
        </template>
    </tfoot>
    
    customFooter: [
        [
            { value: 'Total', class: 'font-bold border-r text-center', attr: { rowspan: 2 } },
            { name: 'total-trousers', class: 'text-right border-r' },
            { name: 'total-skirts', class: 'text-right border-r', },
            { name: 'total-dresses', class: 'text-right border-r' },
            { name: 'total-bracelets', class: 'text-right border-r' },
            { name: 'total-rings', class: 'text-right' },
        ],
        [
            { name: 'total-clothes', class: 'text-center border-r', attr: { colspan: 3 } },
            { name: 'total-accessories', class: 'text-center', attr: { colspan: 2 } },
        ],
    ],
    

    Example Data:

    We demonstrate the table's functionality with sample data containing city names and various clothing items.

    Additional Notes:

    • Styling is achieved using CSS classes defined within the col.class and data.class properties.
    • The provided link offers a full working demo for further exploration.

    External links

    1. Demo: https://framework.fuwafuwa.web.id/examples/simple-table
    2. Explanation: https://framework.fuwafuwa.web.id/docs/simple-table.html#simple-table

    Conclusion:

    This breakdown showcases how Alpine JS empowers us to create dynamic tables with flexible headers, bodies, and footers. This approach simplifies table creation and management, especially for scenarios with frequently changing data.

Top comments (0)