Rowspan is not working properly with ngFor in angular 10

Viewed 526

I have a table populating the data from json, There I have to use Rowspan to map the data properly. Only single value will be used for Rowspan. When I am using rowspan with static table its fine, but when it comes under loop its not coming properly. I have commented the static table code. Here is the code below https://stackblitz.com/edit/angular-haubxs?file=src%2Fapp%2Fapp.component.ts

app.component.html

<hello name="{{ name }}"></hello>
<p>
  Start editing to see some magic happen :)
</p>
<table class="table table-bordered">
  <thead>
    <tr>
      <td colspan="4" class="text-center">
        Document Audit Trail
      </td>
    </tr>
    <tr>
      <th rowspan="3">Certificate Number</th>
      <th>Document Version</th>
      <th>Issued on</th>
      <th>Cancelled on</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let item of data">
      <td rowspan="3" style="vertical-align:middle;">AZ12Q289</td>
      <td>{{item.versionNo}}</td>
      <td>{{item.issuedOn}}</td>

    </tr>
  </tbody>
</table>
<!--<table class="table table-bordered">
    <thead>
      <tr>
        <td colspan="4" class="text-center">
          Document Audit Trail
        </td>
      </tr>
      <tr>
        <th rowspan="3">Certificate Number</th>
        <th>Document Version</th>
        <th>Issued on</th>
        <th>Cancelled on</th>
      </tr>
    </thead>
    <tbody>
      
      <tr>
        <td rowspan="3" style="vertical-align:middle;">AZ12Q289</td>
        <td>Version 1</td>
        <td>19/5/2021 09:28</td>
        <td>22/5/2021 15:28</td>
      </tr>
      <tr>
 
        <td>Version 2</td>
        <td>22/5/2021 15:30</td>
        <td>28/5/2021 19:12</td>
        
      </tr>
      <tr>

        <td>Version 3</td>
        <td>22/5/2021 15:30</td>
        <td>-</td>
        
      </tr>
      
    </tbody>
  </table> -->

app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  name = 'Angular';
  data = [
    {
      versionNo: '1',
      issuedOn: '07/Jul/2021 11:15',
      
    },
    {
      versionNo: '2',
      issuedOn: '07/Jul/2021 11:15',
     
    }
  ];
}
1 Answers

This is because you're adding the <td> with rowspan in each <tr>, and not only in the first one.

So, the first one spans two rows in first column, so the next one will span two rows in second column (since first column is already taken), etc.

So, you will want to have:

  • rowspan depending on number of rows in your data
  • have your <td> with rowspan occur only once, for the first item in your array.

For that you can simply check index and length of the array, like so:

<tbody>
    <tr *ngFor="let item of data; let index = index;">
      <td *ngIf="index === 0" [attr.rowspan]="data.length" style="vertical-align:middle;">AZ12Q289</td>
      <td>{{item.versionNo}}</td>
      <td>{{item.issuedOn}}</td>
    </tr>
  </tbody>

Here is forked stackblitz that works with dynamic number of rows.

Related