How to create an accordion table with Bootstrap and Angular ngFor and fixed indentation?

12,248

Solution 1

After several tries it seems that the table component doesn't fit well into a Bootstrap grid container. I could get good results using only div tags with Bootstrap grid system.

Solution 2

Thanks for your post, it helped steered me in the right direction with my project. I figured I would post what I was doing, even though it's not exactly the same. It may help someone else who is trying the same thing. I stopped using ng-bootstrap's Collapse in order to get this to work. Sorry if my terminology is wrong, I'm new to Angular.

What I was working on was a large table with data pulled from a JSON file. At the end of the table row is a button that, when clicked, shows another row with more data.

I was able to get this working without distorting the original row. Here is my result, along with the CSS I used. I hardcoded some stuff for testing, just FYI.

HTML:

ID of table: subs-table

<ng-container *ngFor="let sub of subs; index as i">
    <tr>
        <th scope="row">{{sub.Name}}</th>
        <td><img src="../../assets/{{sub.Image}}"></td>
        <td>{{sub.Description}}</td>
        <td>
            <button class="btn btn-outline-primary btn-block" type="button" data-toggle="collapse" [attr.data-target]="'#collapse-' + i" [attr.aria-expanded]="false" [attr.aria-controls] = "'collapse-' + i"></button>
        </td>
    </tr>
    <tr>
        <td colspan="4" class="collapse-row">
            <div [attr.id]="'collapse-' + i" class="container collapse out">
                <div class="row">
                    <div class="col">Min Splash Damage: 25</div> 
                    <div class="col">Splash Damage: 35</div>
                    <div class="col">Direct Hit Damage: 60</div>
                    <div class="col">Ink Consumption: 40%</div>
                </div>
            </div>
        </td>
    </tr>
</ng-container>

CSS:

/* Sets button text when clicked. Should combine these later with wildcards */
#subs-table .btn-primary:before {
    content:'Click for details';
}
#subs-table .btn-primary[aria-expanded="true"]:before {
    content:'Close Details';
}
/* Styling of the collapsible row */
#subs-table td.collapse-row {
    border-style: none;
    padding: 0;
}

I hope this helps any passerby!

Share:
12,248
ThCollignon
Author by

ThCollignon

Updated on June 05, 2022

Comments

  • ThCollignon
    ThCollignon almost 2 years

    My goal is to copy this behaviour and to include it in a ngFor loop.

    I've tried several codes, each one having a different issue:

    Try 1:

    <table class="table">
        <tbody>
            <tr *ngFor="let game of games; let i = index" class="clickable-row" data-toggle="collapse" [attr.data-target]="'#gameDetails' + i">
                <td class="text-nowrap">{{game.date}}
                    <div [attr.id]="'gameDetails' + i" class="collapse">
                        <p>Insert a large component in this place</p>
                    </div>
                </td>
                <td class="text-nowrap">{{game.label}}</td>
                <td class="text-nowrap">{{game.score}}</td>
            </tr>
        </tbody>
    </table>
    

    Try 1 result, collapsed:

    Try 1 result, collapsed

    Try 1 result, deployed:

    Try 1 result, deployed

    In the try 1 the problem is that the collapsed component fits in the left cell, impacting the cells at his right.

    Try 2:

    <table class="table">
        <tbody>
            <div *ngFor="let game of games; let i = index">
                <tr class="clickable-row" data-toggle="collapse" [attr.data-target]="'#game2Details' + i">
                    <td class="text-nowrap">{{game.date}}</td>
                    <td class="text-nowrap">{{game.label}}</td>
                    <td class="text-nowrap">{{game.score}}</td>
                </tr>
                <tr [attr.id]="'game2Details' + i" class="collapse">
                    <td colspan="3">Insert a large component in this place</td>
                </tr>
            </div>
        </tbody>
    </table>
    

    Try 2 result, collapsed:

    Try 2 result, collapsed

    Try 2 result, deployed:

    Try 2 result, deployed

    In the try 2 we lose the table indentation when details are collapsed.

    Try 3:

    <table class="table">
        <tbody>
            <tr *ngFor="let game of games; let i = index">
                <table class="table">
                    <tbody>
                        <tr class="accordion-toggle" data-toggle="collapse" [attr.data-target]="'#game4Details' + i">
                            <td>{{game.date}}</td>
                            <td>{{game.label}}</td>
                            <td>{{game.score}}</td>
                        </tr>
                        <tr>
                            <td colspan="3" class="hiddentablerow">
                                <div [attr.id]="'game4Details' + i" class="accordian-body collapse">Insert a large component in this place
                                </div>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </tr>
        </tbody>
    </table>
    

    Try 3 result, collapsed:

    enter image description here

    Try 3 result, deployed:

    enter image description here

    In the try 3 the indentation differs between the different inner tables.

    Is there a way to keep the indentation before and after the deploy of the collapsed row? Or maybe another way using something else than a table ?