Setting Angular Material mat-table column width in column configuration

5k views Asked by At

I have the following column configuration for my Angular Material mat-table columns:

export interface TableColumn {
  name: string;
  dataKey: string;
  isSortable?: boolean;
  width?: string; // column width
}

//...

this.tableColumns = [
    {
        name: 'Id',
        dataKey: 'id',
        position: 'left',
        width: '50px'
    },
    {
        name: 'Name',
        dataKey: 'name',
        position: 'left',
        width: '100%'
    }
];

As far as I see, many people use css in order to set column width as on this page, etc. However, would not it be nice if we set the column widths for each column by pixel and percentage in the this.tableColumns array as the other properties when defining columns? I think I just need a configuration of mat-table, but I am not sure if there is such a config for mat-table. If not, I think I can use [style.width] and set each column by column config value. Any suggestion for that?

2

There are 2 answers

8
Eliseo On BEST ANSWER

In general, you defined the columns based in your array like:

<ng-container *ngFor="let column of tableColumns;let first=first">
        <ng-container [matColumnDef]="column.dataKey">
            <th [style.width]="column.width" mat-header-cell *matHeaderCellDef>
                  {{column.name}}
            </th>
            <td [style.width]="column.width" mat-cell 
                 *matCellDef="let element"> {{element[column.dataKey]}}
            </td>
        </ng-container>
</ng-container>

And your displayedColumns as

this.displayedColumns=this.tableColumns.map(x=>x.dataKey)

NOTE: I supose you defined the width as '50%' or '30px' if only use a number you can use, e.g.

[style.width]="column.width+'px'"

Update imagine you want to create a column with actions buttons, but this buttons can be one, two or three. We can asign to this last colum a width of "1%" and 'white-space: nowrap'

//we has two variables
btDelete:boolean=true;
btEdit:boolean:true;

<ng-container matColumnDef="action">
    <th style="width:1%" mat-header-cell *matHeaderCellDef>
    </th>
    <td style="width:1%;white-space: nowrap;" mat-cell 
         *matCellDef="let element">
        <button *ngIf="btEdit" mat-button (click)="edit(element)">Edit</button>
        <button *ngIf="btDelete" mat-button (click)="delete(element)">Delete</button> 
    </td>
</ng-container>

NOTE: I'm not prety sure what happens with the width of columns because the % total is bigger that 100%

We can try using the mat-table in flex-mode

<ng-container *ngFor="let column of columns">
    <ng-container [matColumnDef]="column.name">
        <mat-header-cell [style.flex]="column.width" *matHeaderCellDef> {{column.width}}</mat-header-cell>
        <mat-cell [style.flex]="column.width" *matCellDef="let element"> {{element[column.name]}} </mat-cell>
    </ng-container>
</ng-container>
<ng-container matColumnDef="action">
    <mat-header-cell style="flex:0 1 auto;visibility:hidden" *matHeaderCellDef>
        <button *ngIf="btEdit" mat-button>Delete</button>
        <button *ngIf="btDelete" mat-button>Delete</button>
    </mat-header-cell>
    <mat-cell style="flex:0 1 auto" *matCellDef="let element"> <button *ngIf="btEdit" mat-button>Edit</button>
        <button *ngIf="btDelete" mat-button>Delete</button></mat-cell>
</ng-container>

See that the column "action" the "head" repeat the buttons -with visibility:hidden-

NOTE: In this case, the "with" -really the flex- is a number, not a %,

0
Delwyn Pinto On

While there isn't a way to define column width in the array, you should be able to define it using ng-style. It is possible to provide column specific properties in the html template, therefore this too should work. An example would be

<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
  <mat-text-column name="position" [headerText]="headerText" [ngStyle]="{'width':'20%'}"></mat-text-column>

  <!-- Change the header text. -->
  <mat-text-column name="name" headerText="Element" [ngStyle]="{'width':'40%'}"></mat-text-column>

  <!-- Provide a data accessor for getting the cell text values. -->
  <mat-text-column name="weight" [dataAccessor]="getWeight" [ngStyle]="{'width':'40%'}"></mat-text-column>
</table>

The result of style.width can also be accomplished by ngStyle, so that too should work in the same way.