ljs
ljs

Reputation: 533

Hide/show a table row when clicking on a link in Angular2

Please don't mark it as a duplicate- I have tried the below links already: 1) Hide/show individual items inside ngFor 2) Angular 2 - expand collapse table row 3) Hide/show individual items inside ngFor in angular 2

Problem:
I am trying to hide/show a table row when clicking on a link in the previous row like below: component.html

<div class="table-responsive" *ngFor="let total of totals; let i=index">
<table class="table">
    <ng-container *ngIf="total">   
            <h4 class="productName">Product: {{total.projectGroup}}</h4>
            <tr>
                <th>Total LOC</th>
                <th>Total Test Coverage</th>
                <th>Total Coverage on New Code</th>
                <th>Total Technical Debt</th>
                <th>Total Issues</th>
            </tr>        
            <tr>
                <td>{{total.totalLOC}}</td>
                <td>{{total.totalCoverage}}</td>
                <td>{{total.totalNewCoverage}}</td>
                <td>{{total.totalTechDebtDays}}</td>
                <td><span *ngIf="total.totalCriticalIssues >= 0">Critical: </span>{{total.totalCriticalIssues}} <br/> <span *ngIf="total.totalNonCriticalIssues >= 0">Non-critical: </span>{{total.totalNonCriticalIssues}}</td>
            </tr>
            <tr>
                <td><a id="{{i}}" class ="a_link"  (click)="toggle[total.projectGroup]=!toggle[total.projectGroup]; expand(total.projectGroup)"> Expand/Collapse</a></td>
            </tr>
            <tr [hidden]="!toggle[total.projectGroup]">                       
                <div class="table-responsive">
                    <table class="table">
                        <tr class="table-header">
                            <th>Project Key</th>
                            <th>Quality Gate</th>
                            <th>LOC</th>
                            <th>Test Coverage</th>
                            <th>Coverage on New Code</th>
                            <th>Technical Debt</th>
                            <th>Issues</th>
                        </tr>  
                        <tr *ngFor="let pjt of indProjects" class="table-condensed">
                            <td>{{pjt.projectKey}}</td>
                            <td>{{pjt.qualityGate}}</td>
                            <td>{{pjt.loc}}</td>
                            <td>{{pjt.coverage}}</td>
                            <td>{{pjt.newCoverage}}</td>
                            <td>{{pjt.techDebtDays}}</td>
                            <td><span *ngIf="pjt.criticalIssues >= 0">Critical: </span>{{pjt.criticalIssues}} <br/> <span *ngIf="pjt.nonCriticalIssues >= 0">Non-critical: </span>{{pjt.nonCriticalIssues}}</td>
                        </tr>
                    </table>
                </div>
            </tr>                
    </ng-container>
</table>

Its working if I click on the same "Expand/Collapse" link 2 times - first it shows and then it hides. But if I click on a link once(it shows) and then click on another link, both of the expansions will show the same data in the inner table( which is the data of the last expansion). What I need is the first expansion should show the data related to that link and second expansion should show the data related to the second one.

Please, any pointers would be helpful. Please let me know if I am not clear in describing the issue.

Upvotes: 1

Views: 3629

Answers (1)

Hugo Noro
Hugo Noro

Reputation: 3243

The problem you are facing here is that you are associating a toggle to an element inside a for loop without actually creating different references. This means that all the generated table rows will point to the same reference so when you click one link it will affect multiple.

Since you are already getting the index on the ngFor loop you should associate that index to the toggle references. The result would become something like this

toggle_1[total.projectGroup]
toggle_2[total.projectGroup]

This way the reference for the action would be kept on each row of the table.

But to simplify what it seems to be your goal you could just have

(click) = “toggle[i] = !toggle[i]”

And then where you have the hidden checking the toggle I would also replace

[hidden]="!toggle[total.projectGroup]"

With

[hidden]="!toggle[i]”

I believe you just need the template flags. Unless you need some more complex behaviour I don’t think you need the component function at all

I have also noticed that you have the second ngFor loop without an index. This will cause issues because when you set the indProjects property it will have the same value for all the rows. So you need to pass the index to your expand(total.projectGroup, i) function and in the template when doing the loop you will need to read from

<tr *ngFor="let pjt of indProjects[i]" class="table-condensed">

This way you will for sure have unique list per row

Upvotes: 2

Related Questions