Search code examples
htmlangularangular6cell

Vertically merge cell in angular 6


I'm trying to merge cell in a angular table but my object is dynamic so I can't fix some value for rowspan attribute...

Here is my actuall html:

 <table class="simple">
                <thead>
                <tr>
                    <th *ngFor="let col of columns"><p class="column-header">{{col}}</p></th>
                </tr>
                </thead>
                <tbody>
                <tr *ngFor="let item of mylist; let i=index" class="p-16 pl-24">
                    <td>{{item.name}}</td>
                    <td>{{item.email}}</td>
                    <td>{{item.number}}</td>
                    <td>{{item.cod}}</td>
                    <td>{{item.pref}}</td>
                </tr>
                </tbody>
            </table>

actual result:

name        |    email      | number        | cod   | pref
-------------------------------------------------------------
maryann     |  m@gmail.com  | 123           | 1     | 22
maryann     |  m1@gmail.com | 2104          | 12    | 22
john        |  j@gmail.com  | 2206          | 11    | 4
john        |  j1@gmail.com | 2205          | 178   | 4
john        |  j2@gmail.com | 2309          | 199   | 4
petter      |  p@gmail.com  | 12            | 150   | 50

expected result:

name        |    email      | number        | cod   | pref
-------------------------------------------------------------
maryann     |  m@gmail.com  | 123           | 1 | 22
            |  m1@gmail.com | 2104          | 12    | 
------------------------------------------------------------
john        |  j@gmail.com  | 2206          | 11    | 4
            |  j@gmail.com  | 2205          | 178   | 
            |  j@gmail.com  | 2309          | 199   | 
------------------------------------------------------------
petter      |  p@gmail.com  | 12            | 150   | 50

Solution

  • You can build a pipe:

    export interface GroupedData {
      name: string;
      pref: number;
      emails: string[]; 
      numbers: (number | string)[]; 
      cods: (number | string)[];
    }
    
    @Pipe({name: 'groupByEmail'})
    export class GroupByEmailPipe implements PipeTransform {
      transform(array: any[]): GroupedData[] {
        const dataByUser: {[key:string]: GroupedData} = {};
        for(const item of array) {
          if(!dataByUser.hasOwnProperty(item.name)) {
            dataByUser[item.name] = {
              name: item.name,
              pref: item.pref,
              emails: [],
              numbers: [],
              cods: [],
            };
          }
    
          dataByUser[item.name].emails.push(item.email ? item.email : '');
    
          // for simplicity, I'm considering that none of the following values can be zero
          dataByUser[item.name].numbers.push(item.number ? item.number : '');
          dataByUser[item.name].cods.push(item.cod ? item.cod : '');
        }
    
        return Object.keys(dataByUser).map(key => dataByUser[key]);
      }
    }
    

    And in your template:

    <table class="simple">
      <thead>
        <tr>
          <th *ngFor="let col of columns"><p class="column-header">{{col}}</p></th>
        </tr>
      </thead>
      <tbody>
        <tr *ngFor="let item of mylist | groupByEmail" class="p-16 pl-24">
          <td>{{item.name}}</td>
          <td><div *ngFor="let value of item?.emails">{{value}}</div></td>
          <td><div *ngFor="let value of item?.numbers">{{value}}</div></td>
          <td><div *ngFor="let value of item?.cods">{{value}}</div></td>
          <td>{{item.pref}}</td>
        </tr>
      </tbody>
    </table>
    

    Don't forget to declare the pipe in the @NgModule's declarations array.