Search code examples
ag-gridag-grid-angularangular13

AG-Grid Sorting wont work properly if there is 'asc' or 'desc' as cell value


While working on my project, I found a strange issue that if a cell have either 'asc' or 'desc' as value, then sorting to that particular AG-Grid column will not work properly.

Screenshot of Issue from Plunker Screenshot of Issue

Here Sorting 'Country Desc' column in Ascending order shows 'desc' related cells after 'Zimbabwe' but it should show 'desc' related cells after 'Denmark'

enter image description here

Please go through the plunker URL : Click here

import {
  HttpClient
} from '@angular/common/http';
import {
  Component
} from '@angular/core';
import {
  ColDef,
  GridReadyEvent
} from 'ag-grid-community';
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-alpine.css';
import {
  IOlympicData
} from './interfaces';

@Component({
  selector: 'my-app',
  template: `<ag-grid-angular
    style="width: 100%; height: 100%;"
    class="ag-theme-alpine"
    [columnDefs]="columnDefs"
    [defaultColDef]="defaultColDef"
    [rowData]="rowData"
    (gridReady)="onGridReady($event)"
  ></ag-grid-angular>`,
})
export class AppComponent {
  public columnDefs: ColDef[] = [{
      field: 'athlete',
      sort: 'desc'
    },
    {
      field: 'age',
      width: 90
    },
    {
      field: 'countryDesc'
    },
    {
      field: 'year',
      width: 90,
      unSortIcon: true
    },
    {
      field: 'date',
      comparator: dateComparator
    },
    {
      field: 'sport'
    },
    {
      field: 'gold'
    },
    {
      field: 'silver'
    },
    {
      field: 'bronze'
    },
    {
      field: 'total'
    },
  ];
  public defaultColDef: ColDef = {
    width: 170,
    sortable: true,
  };
  public rowData!: IOlympicData[];

  constructor(private http: HttpClient) {}

  onGridReady(params: GridReadyEvent < IOlympicData > ) {
    this.http
      .get < IOlympicData[] > (
        'https://www.ag-grid.com/example-assets/olympic-winners.json'
      )
      .subscribe((data) => {

        this.rowData = data.map(x => {
          // preparing the data here
          return { ...x,
            countryDesc: x.country === 'Russia' ? 'desc' : x.country
          };
        });
      });
  }
}

function dateComparator(date1: string, date2: string) {
  const date1Number = monthToComparableNumber(date1);
  const date2Number = monthToComparableNumber(date2);
  if (date1Number === null && date2Number === null) {
    return 0;
  }
  if (date1Number === null) {
    return -1;
  }
  if (date2Number === null) {
    return 1;
  }
  return date1Number - date2Number;
}
// eg 29/08/2004 gets converted to 20040829
function monthToComparableNumber(date: string) {
  if (date === undefined || date === null || date.length !== 10) {
    return null;
  }
  const yearNumber = Number.parseInt(date.substring(6, 10));
  const monthNumber = Number.parseInt(date.substring(3, 5));
  const dayNumber = Number.parseInt(date.substring(0, 2));
  return yearNumber * 10000 + monthNumber * 100 + dayNumber;
}

Though I would have to think of another way of sorting the data to meet my project deadline but any help on this is really appreciated.


Solution

  • You can utilize localeCompare by adding comparator to your defaultColDef like so:

      public defaultColDef: ColDef = {
        width: 170,
        sortable: true,
        comparator: (valueA, valueB) => valueA.localeCompare(valueB),
      };