Search code examples
htmlcssangularangular-materialangular-material-table

Vertical Headings table Angular material


in this example, ( https://stackblitz.com/edit/angular-ivy-xtyoyq?file=src/app/app.component.ts ), we have basic table, but in my case I want to make this table like this :

table, th, td {
  border: 1px solid black;
  border-collapse: collapse;
}
th, td {
  padding: 5px;
  text-align: left;
}
<table style="width:100%">
<tr>
    <th>No.</th>
    <td>1</td>
    <td>2</td>
    <td>3</td>
    <td>4</td>
  </tr>
  <tr>
    <th>Name</th>
    <td>Hydrogen</td>
    <td>Helium</td>
    <td>Lithium</td>
    <td>Beryllium</td>
            
  </tr>
  <tr>
    <th>Weight</th>
    <td>1.0079</td>
    <td>4.0026</td>
    <td>6.941</td>
    <td>9.0122</td>
  </tr>
   <tr>
    <th>Symbol</th>
    <td>H</td>
    <td>He</td>
    <td>Li</td>
    <td>Be</td>
  </tr>
</table>

please help!!


Solution

  • You can use invert the table in an ngOnInit() method in the class to give the required data structure and then iterate over the column list in the HTML to give the required columns. Below is an example:

    Html File:

    <table mat-table [dataSource]="displayData" class="mat-elevation-z8" *ngIf="showTable">
    
      <ng-container [matColumnDef]="column" *ngFor="let column of displayColumns">
        <th mat-header-cell *matHeaderCellDef> {{ column }} </th>
        <td mat-cell *matCellDef="let element"> {{ element[column] }} </td>
      </ng-container>
    
      <tr mat-header-row *matHeaderRowDef="displayColumns"></tr>
      <tr mat-row *matRowDef="let row; columns: displayColumns;"></tr>
    </table>
    

    TS File:

    import {Component, OnInit} from '@angular/core';
    
    @Component({
      selector: 'table-basic-example',
      styleUrls: ['table-basic-example.css'],
      templateUrl: 'table-basic-example.html',
    })
    export class TableBasicExample implements OnInit {
      inputColumns = ['position', 'name', 'weight', 'symbol'];
      inputData = ELEMENT_DATA;
    
      displayColumns: string[];
      displayData: any[];
      showTable: boolean;
    
      ngOnInit() {
        this.displayColumns = this.inputData.map(x => x.position.toString());
        this.displayData = this.inputColumns.map(x => this.formatInputRow(x));
    
        console.log(this.displayColumns);
        console.log(this.displayData);
    
        this.showTable = true;
      }
    
      formatInputRow(row) {
        const output = {};
    
        for (let i = 0; i < this.inputData.length; ++i) {
          output[this.inputData[i].position] = this.inputData[i][row];
        }
    
        return output;
      }
    }
    
    export interface PeriodicElement {
      name: string;
      position: number;
      weight: number;
      symbol: string;
    }
    
    const ELEMENT_DATA: PeriodicElement[] = [
      {position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
      {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
      {position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
      {position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
      {position: 5, name: 'Boron', weight: 10.811, symbol: 'B'},
      {position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'},
      {position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
      {position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'},
      {position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'},
      {position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'},
    ];
    

    Working Example here