noclist
noclist

Reputation: 1819

reusable Angular Material mat-table

I have the following Angular Material mat-table for listing Employees. I also have other tables I need to convert to this same style and structure. How can I componentize this Employee table for reuse? The point of using a component library like Material is to reuse common components, I'm having trouble understanding how this table can be reused easily.

<table mat-table matSort [dataSource]="employeeDisplayList" class="mat-elevation-z8 table">

  <ng-container matColumnDef="selected">
    <th mat-header-cell *matHeaderCellDef></th>
    <td mat-cell *matCellDef="let element; let i = index"
      [ngClass]="{'dependent': element.relationship !== 'Primary'}">
      <input type="checkbox" id="enrollEmployee-{{ i }}" name="enrollEmployee">
      <label for="enrollEmployee-{{ i }}"></label>
    </td>
</ng-container>

<!-- Employee Name Column -->
<ng-container matColumnDef="employeeName">
  <th mat-header-cell *matHeaderCellDef mat-sort-header> Employee Name </th>
  <td mat-cell *matCellDef="let element" 
    [ngClass]="{'dependent': element.relationship !== 'Primary'}"> {{element.employeeName}} </td>
</ng-container>

<!-- Relationship Column -->
<ng-container matColumnDef="relationship">
  <th mat-header-cell *matHeaderCellDef mat-sort-header> Relationship </th>
  <td mat-cell *matCellDef="let element"
    [ngClass]="{'dependent': element.relationship !== 'Primary'}"> {{element.relationship}} </td>
</ng-container>

<!-- Medical Column -->
<ng-container matColumnDef="medical">
  <th mat-header-cell *matHeaderCellDef mat-sort-header> Medical </th>
  <td mat-cell *matCellDef="let element"
    [ngClass]="{'dependent': element.relationship !== 'Primary'}"> {{element.medical}} </td>
</ng-container>

<!-- Plan Name Column -->
<ng-container matColumnDef="planName">
  <th mat-header-cell *matHeaderCellDef mat-sort-header> Plan Name </th>
  <td mat-cell *matCellDef="let element"
    [ngClass]="{'dependent': element.relationship !== 'Primary'}"> {{element.planName}} </td>
</ng-container>

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

</table>

TS:

  displayedColumns: string[] = ['selected', 'employeeName', 'relationship', 'medical', 'planName'];
  @ViewChild(MatSort) sort: MatSort;

  ngOnInit() {
    this.employeeList = this.enrollmentService.getEmployees();
    this.employeeDisplayList = new MatTableDataSource(this.employeeList);
    this.employeeDisplayList.sort = this.sort;
  }

Upvotes: 0

Views: 1223

Answers (1)

Eliseo
Eliseo

Reputation: 57909

the first step is "parametrize" your table. For this, you can use an array of object and auxliar variable

You give a few clues, but I can imagine you can has, e.g.

//an array like
columnSchema=[
   {title:"Employed Name",column:"employeeName"}
   {title:"Relationship ",column:"relationship}
   ...
]
//two variables
columnCompare="relationship"
valueCompare="Primary"
//your displayColumns is realional with columSchema
displayColumns=["selected",...this.columSchema.map(x=>x.column)]
//and use datasource as data source

Then you can create your table like

<table mat-table matSort [dataSource]="dataSource" class="mat-elevation-z8 table">
   <!--the "selected is fixed for all the tables-->
  <ng-container matColumnDef="selected">
    <th mat-header-cell *matHeaderCellDef></th>
    <td mat-cell *matCellDef="let element; let i = index"
      [ngClass]="element[columnCompare]==valueCompare?'dependent':null">
      <input type="checkbox" id="enrollEmployee-{{ i }}" name="enrollEmployee">
      <label for="enrollEmployee-{{ i }}"></label>
    </td>
   </ng-container>
   <!--the rest columns use the columnSchema-->
   <ng-container *ngFor="let column of columnSchema" [matColumnDef]="column.column">
      <th mat-header-cell *matHeaderCellDef mat-sort-header>{{column.title}}</th>
      <td mat-cell *matCellDef="let element" 
           [ngClass]="element[columnCompare]==valueCompare?'dependent':null"> 
           {{element[column.column]}}
      </td>
    </ng-container>
  ...
</table>

Well, we need now convert ours variables in @Input of our component, as displayColumns depending of "columnSchema" use a setter

displayColumns;
_columnSchema;
@Input() dataSource
@Input() columnCompare
@Input() valueCompare
@Input() set columnSchema(value)
{
    this._columnsSchema=value
    this.displayColumns=["selected",...value.map(x=>x.column)]
  
}
get columnSchema()
{
     return this._columnSchema
}

Well, create a component and use like

<myComponent 
   [dataSource]="employeeDisplayList"
   [columnSchema]="columnSchema"
   [columnCompare]="'relationship'"
   [valueCompare]="'Primary'">
</myComponent>

There are a lot of more things you can do it, but I hope this help you a few

Upvotes: 3

Related Questions