5

I have multiple Cards in a For loop. In each card, I would like to show and hide content inside the card using a link or a button. I do not have unique Ids to assign each div I want to toggle. Is there a way to do this?

The following code expands or collapses the content in the first card only, even if any "Expand" or "Collapse" button is clicked in any card.

<div *ngFor="let result of results">
    <div class="clr-col-lg-12 clr-col-12">
        <div class="card">
            <div class="card-block">
                <div *ngIf="result?.name">
                    <h3 class="card-title">{{result.name}}</h3>
                </div>

                <div class="expandCollapse">
                    <button (click)="toggle($event)">
                        {{buttonName}}
                    </button>
                </div>
                <div class="expandCollapseContent" *ngIf="showRuleContent">
                    <div *ngIf="result?.cTag">
                        <h5>C Tag</h5>{{result.cTag}}
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

Component

public showRuleContent:boolean = false;
public buttonName:any = 'Expand';

toggle($event) {
  this.showRuleContent = !this.showRuleContent;

  // CHANGE THE NAME OF THE BUTTON.
  if(this.showRuleContent)  
    this.buttonName = "Collapse";
  else
    this.buttonName = "Expand";
}
Jake
  • 25,479
  • 31
  • 107
  • 168
  • You can bind to [hidden] . see https://stackoverflow.com/questions/35163009/angular-2-show-and-hide-an-element – jcuypers May 02 '19 at 17:31

2 Answers2

7

You can use an array which holds the visible state of each element instead of a single variable.

Template

<div *ngFor="let result of results;let i = index">
    <div class="clr-col-lg-12 clr-col-12">
        <div class="card">
            <div class="card-block">
                <div *ngIf="result?.name">
                    <h3 class="card-title">{{result.name}}</h3>
                </div>

                <div class="expandCollapse">
                    <button (click)="toggle(i)">
                        {{hideRuleContent[i] ? 'Expand' : 'Collapse'}}
                    </button>
                </div>
                <div class="expandCollapseContent" *ngIf="!hideRuleContent[i]">
                    <div *ngIf="result?.cTag">
                        <h5>C Tag</h5>{{result.cTag}}
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

Component

public hideRuleContent:boolean[] = [];
public buttonName:any = 'Expand';

toggle(index) {
  // toggle based on index
  this.hideRuleContent[index] = !this.hideRuleContent[index];
}
Pranav C Balan
  • 113,687
  • 23
  • 165
  • 188
2

Here is a neat way to hide/show items in a list. You can use template element properties instead of storing something in an array.

Note how it takes advantage of Angular's template variables (#ContentElement).

<ng-container *ngFor="let item of list">
  <div #ContentElement></div>
  <button (click)="toggle(ContentElement)">Toggle</button>
</ng-container>
// Maybe there are other ways to do this part, here is an example.
// Idea here is to toggle a class.
toggle(e: HTMLElement) {
  e.classList.toggle('hidden');
}
.hidden {
   display: none;
}

If instead of hiding, you want to remove the element from the DOM:

close(e: HTMLElement) {
  e.remove();
}
Community
  • 1
  • 1
Rui Marques
  • 8,567
  • 3
  • 60
  • 91