'angular2 material table hide column

I have the following angular2 material table

<mat-table #table [dataSource]="dataSource" >

        <!--- Note that these columns can be defined in any order.
              The actual rendered columns are set as a property on the row definition" -->

        <!-- Position Column -->
        <ng-container matColumnDef="selected">
            <mat-header-cell *matHeaderCellDef>
                <mat-checkbox [(ngModel)]="selectAll"></mat-checkbox>
            </mat-header-cell>
            <mat-cell *matCellDef="let element">
                <mat-checkbox [(ngModel)]="element.selected" [checked]="selectAll"></mat-checkbox>
            </mat-cell>
        </ng-container>

        <ng-container matColumnDef="id">
            <mat-header-cell *matHeaderCellDef> Id</mat-header-cell>
            <mat-cell *matCellDef="let element"> {{element.id}}</mat-cell>
        </ng-container>

        <ng-container matColumnDef="requested_status">
            <mat-header-cell *matHeaderCellDef> Status</mat-header-cell>
            <mat-cell *matCellDef="let element"> {{element.requested_status}}</mat-cell>
        </ng-container>
        ......

I need to hide a column in the table by some boolean condition. Is it possible without changing columns map in my component?

displayedColumns = ['selected', 'id', ...];

I tried to use *ngIf but it doesn't work. How to do that?



Solution 1:[1]

no need of any directives.

just use

[hidden] it will work ex:[hidden]="show" in html and set show to boolean in ts file.

my html code:

<ng-container matColumnDef="department" >
  <mat-header-cell [hidden]="show" *matHeaderCellDef> 
    Department 
  </mat-header-cell>
  <mat-cell [hidden]="show" *matCellDef="let element">
    {{element.department}}
  </mat-cell>
</ng-container>

Solution 2:[2]

The angular way to do this is to update the columns passed to your row template:

HTML:

<mat-row *matRowDef="let row; columns: getDisplayedColumns();"></mat-row>

TS:

const columnDefinitions = [
  { def: 'col1', showMobile: true },
  { def: 'col2', showMobile: false },
];

getDisplayedColumns(): string[] {
  const isMobile = this.currentDisplay === 'mobile';
  return this.columnDefinitions
    .filter(cd => !isMobile || cd.showMobile)
    .map(cd => cd.def);
}

Solution 3:[3]

To the column you want to hide, add this:

[style.display]="'none'"

You should add to both the mat-heather-cell and the mat-cell.

Solution 4:[4]

I'm using Angular Flex Responsive API (https://github.com/angular/flex-layout/wiki/Responsive-API). Example:

     <ng-container matColumnDef="date">
        <th
          *matHeaderCellDef
          mat-header-cell
          mat-sort-header
          fxShow
          fxHide.lt-sm
        >
          Data
        </th>
        <td *matCellDef="let element" mat-cell fxShow fxHide.lt-sm>
          {{ element.date | date: "dd/MM/yyyy" }}
        </td>
        <td *matFooterCellDef mat-footer-cell fxShow fxHide.lt-sm>Total</td>
      </ng-container>

In this case, will hide in screen less than small (lt-sm).

Solution 5:[5]

The only possible solution seems to change displayed columns in the component class

displayedColumns = ['selected', 'id', ...];

Solution 6:[6]

Finally i found a way to hide column without changing columns map. We need to create an attribute directive, through this directive we can set the display property of an element.

ShowColumnDirective:

import {Component, Directive, ElementRef, Input, AfterViewInit} from '@angular/core';
@Directive({ 
     selector: '[showCoulmn]' 
})
export class ShowColumnDirective implements AfterViewInit{
    @Input() showInput: string;
    constructor(private elRef: ElementRef) { 
    }
    ngAfterViewInit(): void {
    this.elRef.nativeElement.style.display = this.showInput;
    }
}

Declare this directive in AppModule or any other module:

import {TableBasicExample} from './table-basic-example';
import {ShowColumnDirective} from './table-basic-example';
@NgModule({

  imports: [
    ..........
  ],

  declarations: [TableBasicExample, ShowColumnDirective],
  bootstrap: [TableBasicExample],
  providers: []
})
export class AppModule {}

Now we can use the directive inside our table's html Component:

<ng-container matColumnDef="position">
  <mat-header-cell showCoulmn showInput="none" *matHeaderCellDef> No. </mat-header-cell>
  <mat-cell showCoulmn showInput="none"    *matCellDef="let element"> {{element.position}} </mat-cell>
</ng-container>

Here is working template: https://plnkr.co/edit/Woyrb9Yx8b9KU3hv4RsZ?p=preview

Solution 7:[7]

If you are going to hide a row by some changeable condition I suggest following way:

// css
.hidden-row {
  display: none;
}

// html
<ng-container matColumnDef="importDate">
  <mat-header-cell *matHeaderCellDef [ngClass]="showColumn()">
      Date
  </mat-header-cell>
  <mat-cell *matCellDef="let element" [ngClass]="showColumn()">
      {{element?.importDate}}
  </mat-cell>
</ng-container>

// ts
showColumn(): string {
  return this.someService.hasAccess() ? null : 'hidden-row';
}

Solution 8:[8]

The proposed solution @John Smith didn't work form me. Instead I used this adjustment:

 // css
 .hidden-item {
   display: none;
 }

 // html
 <ng-container matColumnDef="importDate">
   <mat-header-cell *matHeaderCellDef [ngClass]="{'hidden-item': showColumn()}"> Date
   </mat-header-cell>
   <mat-cell *matCellDef="let element" [ngClass]="{'hidden-item': showColumn()}"> {{element?.importDate}}
   </mat-cell>
 </ng-container>

 // ts
 showColumn(): boolean {
   return this.someService.hasAccess();
 }

Solution 9:[9]

It's possible as explained in this wrong issue: https://github.com/angular/material2/issues/8944

View:

<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>

class:

displayedColumns = ['tab1', 'tab2', 'tab3'];

but in constructor:

if (this.removeOneColumn) this.displayedColumns = ['tab1', 'tab3'];

Solution 10:[10]

I had the same problem, where the user can display or hide columns through a checkbox. I solve my problem through a pipe, like this:

@Component({
  selector: "app-dynamic-table",
  template: `
    <mat-checkbox *ngFor="let column of columns" [(ngModel)]="column.show">{{column.name | titlecase}}</mat-checkbox>
    <mat-table #table [dataSource]="dataSource">
      ....
      <mat-header-row *matHeaderRowDef="displayedColumns | toggleColumns:columns;"></mat-header-row>
      <mat-row *matRowDef="let row; columns: displayedColumns | toggleColumns:columns;"></mat-row>
    </mat-table>
  `
})
export class DynamicTableComponent {
  private _columns = [
    {
      name: "date",
      show: true
    }, {
      name: "selected",
      show: true
    }, {
      name: "id",
      show: true
    }, {
      name: "location",
      show: true
    }
  ];

  get columns() { return this._columns; }
  get displayedColumns(): string[] { return this._columns.map(c => c.name); }
}

@Pipe({
  name: "toggleColumns"
})
export class ToggleColumnsPipe implements PipeTransform {
  transform(displayedColumns: string[], columns): string[] {
    displayedColumns = columns.filter(c => !!c.show).map(c => c.name);
    return displayedColumns;
  }

}

Now you just need to manage to change the show attribute of the column from true <=> false so the column will be disappear if show: false and it will be displayed when show: true. I do that as you see with mat-checkbox.

Solution 11:[11]

There's a way which is writing some dirty code for both html and css codes, say, specify each column with an identifier then set a rule (like display: none;) to hide them when necessary. Considering that a table will produced row by row, not column by column.

But the correct way is the common & easiest way which is changing column map in component (for example, when an event fires).

Solution 12:[12]

For my case, the below css code is not working.

display:none 

Thanks to Rod Astrada, I try add the below code into mat-header-cell then working, then it works!

[style.display]="'none'"

like the following example:

      <ng-container matColumnDef="id">
        <mat-header-cell *matHeaderCellDef [style.display]="'none'">Id</mat-header-cell>
        <mat-cell *matCellDef="let element" [style.display]="'none'"> {{element.id}} </mat-cell>
      </ng-container>

Solution 13:[13]

For Example:

In HTML:

<button mat-raised-button color="primary" (click)="show_hide_details()">
    <span *ngIf="showHideDetails== true">Hide Details</span>
    <span *ngIf="showHideDetails== false">Show Details</span>
</button>

<ng-container matColumnDef="Cost">
    <th mat-header-cell *matHeaderCellDef mat-sort-header
    [ngStyle]="{display: showHideDetails === true? 'table-cell' : 'none'}">{{'Cost' | translate}}</th>

    <td mat-cell *matCellDef="let element" [ngStyle]="{display: showHideDetails === true? 
     'table-cell' : 'none'}">{{element.cost}} </td>
</ng-container>

In TS:

showHideDetails: boolean = false;

show_hide_details() {
this.showHideDetails= !this.showHideDetails;
}

Solution 14:[14]

You can use this method For delete Or add column in mat-table.

columnsToDisplay: string[] = ['id', 'vcName', 'vcFamily', 'Phone']


  addOrRemoveTableColumn(colName: string, index: number) {

    if ( this.columnsToDisplay.filter(q => q.valueOf() == colName).length > 0) {
      this.columnsToDisplay = this.columnsToDisplay.filter(q => q.valueOf() != colName);
    }
    else if (this.columnsToDisplay.filter(q => q.valueOf() == colName).length == 0) {
      this.columnsToDisplay.splice(index, 0, colName);
    }
  }

For Example:

this.addOrRemoveTableColumn("id",6);

Solution 15:[15]

The responsiv way:

hope it still helps :)

in TS:

styleUrls: ['style.component.scss'],

in style.component.scss:

  /* language=SCSS */
.hidden {
    display: none;
}

@media (min-width: 1280px) {
    .lg\:block {
        display: table-cell !important;
    }
} 

in HTML:

  <table mat-table
         [dataSource]="dataSource">
   
    <th class="hidden lg:block"
        mat-header-cell
        *matHeaderCellDef>HEADER
    </th>

    <td class="hidden lg:block"
        mat-cell
        *matCellDef="let item">{{ item.data }} </td>

   </table>