Applying an ngClass on only 1 element of a table in angular

67 Views Asked by At

In my table, I'm attempting to add a read more button to each row that has a paragraph. The button is displayed for each row, and when I click one, it operates concurrently for each row.

Here is my code:

<table class="table">
  <thead>
    <tr>
      <th scope="col">Text</th>
      <th scope="col">Date</th>
      <th scope="col">Comments</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let p of posts[0].posts">
      <div [ngClass]="{'limitTextHeight': isReadMore}">
        <td>{{p.post_text}}</td>
      </div>
      <button type="button" (click)="showText()" style="margin-top:15px">
        {{ isReadMore ? 'Read More': 'Read Less' }}
      </button>
      <td>{{p.post_date}}</td>
      <td>{{p.post_comments.length}} comment</td>
    </tr>
  </tbody>
</table>

and my showText() function:

showText() {
    this.isReadMore = !this.isReadMore
 }
2

There are 2 best solutions below

0
Prashant Singh On BEST ANSWER

This is happening because you're using single boolean variable i.e, isReadMore for all the looped tr tag.

What you can do is posts[0].posts map this posts with one more key that can be anything for example isReadMore in your case, then you will get unique instance to handle for each para, like this. {{ p?.isReadMore ? 'Read More': 'Read Less' }}. Hope you understood what I'm trying to say.

0
Mirco On

You are using a common variable for all the rows. That's why when you click one they all change. You should use local ones, one for each row like so:

 <table class="table">
  <thead>
    <tr>
      <th scope="col">Text</th>
      <th scope="col">Date</th>
      <th scope="col">Comments</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let p of posts[0].posts">
      <div [ngClass]="{'limitTextHeight': isReadMore}">
        <td>{{p.post_text}}</td>
      </div>
      <button type="button" (click)="showText(p)" style="margin-top:15px">
        {{ p.isReadMore ? 'Read More': 'Read Less' }}
      </button>
      <td>{{p.post_date}}</td>
      <td>{{p.post_comments.length}} comment</td>
    </tr>
  </tbody>
</table>

and the showText() function:

showText(post) {
    post.isReadMore = !post.isReadMore
 }

You could also add an *ngIf to check if there is text long enough before showing the button:

<button type="button" *ngIf="p.post_text?.length > 20" (click)="showText(p)" style="margin-top:15px">
    {{ p.isReadMore ? 'Read More': 'Read Less' }}
</button>