Home > Software engineering >  Applying an ngClass on only 1 element of a table in angular
Applying an ngClass on only 1 element of a table in angular

Time:09-09

I'm trying to add a read more button to every row that has a paragraph in my table! the problem is that the button is showing for every row and it's working simultaneously for all the rows when I click one.

Here is my code:

<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
 }

CodePudding user response:

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.

CodePudding user response:

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 >
  <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>
  • Related