'Angular and Bootstrap - collapse in loop doesn't show for the last element
Angular version: 13.2.4 Bootstrap version: 5.0.0
I'm implementing a feature in my app that would generate a table with data that would display information for each object of type Actor - and I'm using an *ngFor loop to do this. I want to use a collapse in my HTML file that would show only after clicking a button, and that collapse would show only for a given Actor. I've tried to implement a some sort of dynamic ID for each of the collapse, because otherwise when I click the button to show it, collapses for all of the actors were showing (including the last one) - and I'm pretty convinced the issue is related to this. The problem is, my current approach with the dynamic ID works for every Actor just fine, but not for the last one - I click the button and nothing happens. My idea is that I've messed something up with id HTML attributes and it seems an easy to fix bug, but I just don't see it. This is how the malfunctioning part looks like:
<div class="row">
<div class="col">
<div>
Temporary Hit Points: {{actor.getTemporaryHitPoints().getHitPoints()}}
Turns left: {{actor.getTemporaryHitPoints().getTurnsLeft()}}
</div>
</div>
<div class="col">
<p>
<a class="btn btn-primary" data-bs-toggle="collapse" href="#{{actor.name}}TemporaryHitPoints"
role="button" aria-expanded="false" aria-controls="collapseExample">
Add temporary Hit Points
</a>
</p>
</div>
</div>
<div class="row">
<div class="collapse" id="{{actor.name}}TemporaryHitPoints">
<input type="number" class="input" placeholder="Hit Points amount"
(keyup)="setTemporaryHitPointsToAdd($event)"
>
<input type="number" class="input" placeholder="Duration (leave blank if permanent)"
(keyup)="setTemporaryHitPointsToAddDuration($event)"
>
<button class="btn btn-primary" (click)="onSubmitTemporaryHitPoints(actor)">Submit</button>
</div>
</div>
Solution 1:[1]
Ok, so I've managed to fix this. As I'm pretty new to this, I discovered that instead of pure Boostrap, there's ng-boostrap tool designed to use Bootstrap specifically with Angular, which led me to the ng-bootstrap's collapse documentation. With its help, I've done these small changes to my code:
- I've moved the whole code shown in the question to a separate component
- I've removed any HTML
idreferences as they are no longer needed - I've added a click event and a corresponding function to the button which just changes the newly added
isCollapsedproperty value betweentrueandfalse
So the code changes were:
HTML:
<a class="btn btn-primary" data-bs-toggle="collapse" href="#{{actor.name}}TemporaryHitPoints"
role="button" aria-expanded="false" aria-controls="collapseExample">
Add temporary Hit Points
</a>
was changed to
<a class="btn btn-primary" data-bs-toggle="collapse"
role="button" aria-expanded="false" (click)="showTemporaryHitPoints()">
Add temporary Hit Points
</a>
and the Typescript class added code:
isCollapsed: boolean = true;
//...
showTemporaryHitPoints(): void {
this.isCollapsed = !this.isCollapsed;
}
- The collapse
divnow just has a binding to this property. So instead of this line:
<div class="collapse" id="{{actor.name}}TemporaryHitPoints">
There's now this one:
<div [ngbCollapse]="isCollapsed">
Not sure if this is the best solution, but it certainly works as intended.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Jack_Russell |
