2

Im probably being stupid but as far as i can tell, below code should follow examples from angular material website exactly. however, the sorting result is incorrect.

I can see sorting happened because order changed. row xxx50 became the first row. row xxx01 moved to original position of xxx50. the rest of the data in original order. asc and des result in same order.

Please show me what im doing wrong.

html:

<div class="mat-elevation-z8">
    <table mat-table [dataSource]="dataSource" matSort>
        <ng-container matColumnDef="agent">
        <th mat-header-cell *matHeaderCellDef mat-sort-header>Agent</th>
            <td mat-cell *matCellDef="let relationshipInterface"> {{relationshipInterface.agentDisplayName}} </td>
        </ng-container>
        <ng-container matColumnDef="player">
            <th mat-header-cell *matHeaderCellDef mat-sort-header>Player</th>
            <td mat-cell *matCellDef="let relationshipInterface"> {{relationshipInterface.playerDisplayName}} </td>
        </ng-container>
        <ng-container matColumnDef="avatar">
            <th mat-header-cell *matHeaderCellDef mat-sort-header>Nickname</th>
            <td mat-cell *matCellDef="let relationshipInterface"> {{relationshipInterface.avatarDisplayName}} </td>
        </ng-container>

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

    <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>
</div>

ts:

import { Component, OnInit, ViewChild } from '@angular/core';
import { MatPaginator, MatSort, MatTableDataSource } from '@angular/material';

export interface RelationshipInterface {
  agentName: string;
  agentDisplayName: string;
  playerName: string;
  playerDisplayName: string;
  avatarName: string;
  avatarDisplayName: string;
}

@Component({
  selector: 'app-relationships-table',
  templateUrl: './relationships-table.component.html',
  styleUrls: ['./relationships-table.component.css']
})
export class RelationshipsTableComponent implements OnInit {
  displayedColumns: string[] = ['agent', 'player', 'avatar'];
  dataSource: MatTableDataSource<RelationshipInterface>;

  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort) sort: MatSort;

  constructor() {

  }

  ngOnInit() {
    this.dataSource = new MatTableDataSource(
      this.getTempData()
    );
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  }

  applyFilter(filterColumn: string, filterValue: any) {
  }

  getTempData() {
    const newData = [];
    for (let i = 0; i < 100; i++) {
      let str: string;
      if (i < 10) {
        str = '0' + i;
      } else {
        str = '' + i;
      }
      const relationshipInterface = {
        agentName: 'agent name ' + str,
        agentDisplayName: 'agent dName ' + str,
        playerName: 'player name ' + str,
        playerDisplayName: 'player dName ' + str,
        avatarName: 'avatar name ' + str,
        avatarDisplayName: 'avatar dName ' + str,
      };
      newData.push(relationshipInterface);
    }
    return newData;
  }
}
Michael Zhou
  • 41
  • 1
  • 8

2 Answers2

2

after testing, apparently, column names must match data source property names.

i.e.

html:

<ng-container matColumnDef="agent">

ts:

export interface RelationshipInterface {
  agent: string; // was agentDisplayName
}
Michael Zhou
  • 41
  • 1
  • 8
0

Putting this out there since it is the first hit on Google. If anyone else comes across this issue;

My first problem was that some of the strings I was sorting had white spaces in the beginning of the string. This resulted in weird sorting being done.

The second problem was that MatSort is case sensitive (https://github.com/angular/components/issues/9205). This means it sorts large letters first, then small letters. The list AbCd will be sorted as ACbd.

Solution: Use the sortingDataAccessor to manipulate the data to be sorted before it is passed to the sort functionality. string.trim() removes white space characters in beginning and end of string. It can then be returned as string.toLowerCase() to ensure all data is sorted case insensitively.

Example:

@ViewChild(MatSort, { static: false }) set content(sort: MatSort) {
    if (this.dataSource) {
      this.dataSource.sortingDataAccessor = (item, property) => {
        switch (property) {
          case 'description':
            return this.cleanData(item.description);
          case 'name':
            return this.cleanData(item.name);
          default:
            return item[property] || '';
        }
      };
      this.dataSource.sort = sort;
    }
  }

    private cleanData(sortString: string): string {
    let cleanString = '';
    if (sortString) {
      cleanString = sortString.trim();
    }
    return cleanString.toLowerCase();
  }
Zaith
  • 21
  • 1