Thursday, February 6, 2020

column sorting at an Angular Material table

This offered some advice, allowing this...

<table mat-table class="lessons-table mat-elevation-z8" [dataSource]="dataSource">
   <ng-container [matColumnDef]="column.name" *ngFor="let column of
         contents.columns; let i=index">
      <th mat-header-cell *matHeaderCellDef>{{column | findHeader}}</th>

 
 

...to become:

<table mat-table matSort (matSortChange)="sortData($event)"
      class="lessons-table mat-elevation-z8" [dataSource]="dataSource">
   <ng-container [matColumnDef]="column.name" *ngFor="let column of
         contents.columns; let i=index">
      <ng-container *ngIf="!column.isToDisallowSorting; else disallowSorting">
         <th mat-header-cell *matHeaderCellDef [mat-sort-header]="column.name">
               {{column | findHeader}}</th>
      </ng-container>
      <ng-template #disallowSorting>
         <th mat-header-cell *matHeaderCellDef>{{column | findHeader}}</th>
      </ng-template>

 
 

Also I added the following methods to my component, a generic grid that should be able to accomodate any dataset:

   public sortData(sort: Sort) {
      if (!sort.active) {
         return;
      }
      let isAscending:boolean = sort.direction === 'asc';
      let baseType:BaseType = this.contents.columns.find(x => x.name ==
            sort.active).baseType;
      this.contents.data = this.contents.data.sort((a, b) => {
         return this.compare(a[sort.active], b[sort.active], isAscending, baseType);
      });
      this.setStage();
   }
   
   private compare(a: any, b: any, isAscending: boolean, baseType: BaseType) {
      let A:any = this.tryToAccountForNulls(a, baseType);
      let B:any = this.tryToAccountForNulls(b, baseType);
      if (A === B) return 0;
      return (A < B ? -1 : 1) * (isAscending ? 1 : -1);
   }
   
   private tryToAccountForNulls(ab: any, baseType: BaseType){
      if (ab || ab === 0) {
         return ab;
      }
      switch(baseType){
         case BaseType.Array:
            return [];
         case BaseType.Boolean:
            return false;
         case BaseType.Date:
            return new Date(1970, 0, 1);
         case BaseType.Number:
            return 0;
         case BaseType.Object:
            return {};
         case BaseType.String:
            return "";
         default:
            return ab;
      }
   }
}

 
 

The object and array options here are pretty silly, eh? All that I am doing is making a new pointer which cannot be greater than, less than, or equal to a similar pointer so (you guessed it) my if (A === B) return 0; comparison is sabotaged in that regard. Nuts! I could hand in an extra metadata property for which property on an object to sort by I guess. Also, I may need an option for an enum so I could sort by the string values for the enum instead of just the number.

No comments:

Post a Comment