PrimeNG DataTable Custom Sorting or filtering (Angular 2)

18,059

Solution 1

I solved this issue using moment.js, because it's easier and faster, but always code can be customized a little bit if You want to do it without any frameworks (i hope few more if conditions, and string conversions)

So You have to add moment.js to Your project: a) by adding src link to your main html index file (where is main angular selector, polyfills etc.) from this site https://cdnjs.com/libraries/moment.js/ b) but if it's production i recommend to add it via npm. http://momentjs.com/docs/ here are other possibilities.

Then you must declare moment variable under import statements and above @Component annotation

declare var moment;

then if u already have primeng module added to Your project, in the html file within primeng's p-dataTable tag there is p-column tag and here within this tag we need to add sortable="custom" and (sortFunction)="mysort($event)" like so:

<p-column field="date" header="Data" sortable="custom" (sortFunction)="mysort($event)"></p-column>

Date displayed with p-column tag is in DD.MM.YYYY string format like e.g: 03.01.2017

After that in component where we are fetching and pushing data to array, which is used to display data in a table, in my example named appointments we need to add function named mysort (because we are calling this function in html p-column tag)

mysort(event) {
    let comparer = function (a, b): number {
      let formatedA = moment(a.date, "DD.MM.YYYY").format('YYYY-MM-DD');
      let formatedB = moment(b.date, "DD.MM.YYYY").format('YYYY-MM-DD');
      let result: number = -1;

      if (moment(formatedB).isBefore(formatedA, 'day')) result = 1;
      return result * event.order;
    };

    this.appointments.sort(comparer);
}

in my example a.date and b.date is a string like "21.12.2016" that we need to format to YYYY-MM-DD. Then we just are comparing dates.

And just it, i checked this code and it works. I hope it will help someone, and excuse me if explanation was written in tutorial style but this is my first answer and i wanted to do it in the right way :)

Solution 2

I solved it the same way as Relis. However, it didn't work until I reassigned the "this.appointments" variable.

  mysort(event) {

     this.appointments.sort((appointmentA, appointmentB) => {

     // Here the property date is a date string with the format 'dd/mm/yyyy'. 
     // In the constructor of moment(), the second paramater is 
     // the format of the string you're passing in.
     const momentA = moment(appointmentA.date, 'dd/mm/yyyy');
     const momentB = moment(appointmentB.date, 'dd/mm/yyyy');

     if(momentB.isBefore(momentA)){
       result = 1;
     }

     return result * event.order;
   });

    // This is the key here.
    this.appointments = [...this.appointments];
    }
Share:
18,059
Rohit Sindhu
Author by

Rohit Sindhu

Updated on June 06, 2022

Comments

  • Rohit Sindhu
    Rohit Sindhu about 2 years

    I am facing issue in sorting/Filtering date column in PrimeNg Datatable.As i am displaying date "dd/mm/yyyy" string .

    1. if is use template to display "dd/mm/yyyy" then filter is not working as filter working on actual data bind which is in date ISO format.
    2. if convert data to string format from the back end then sort is not correct as it sort on string instead of date.
  • comeback4you
    comeback4you almost 7 years
    what about if time and data both come?
  • comeback4you
    comeback4you almost 7 years
    if time and data both compare .format('YYYY-MM-DD HH:mm:ss'); --> (moment(formatedB).isBefore(formatedA)) result = 1; just removed 'day' keyword it will compare date and time both
  • Joe
    Joe over 5 years
    @Relis - Can you please post the whole project with simple example (Angular + Node) to see how is all wired together?