29

I try to sort the array object by date for my Angular 6 application. The data has string format. I wonder if there is an existing module to perform sort in Angular or we have to build sort function it in Typescript.

Angular Template

<app-item *ngFor="let item of someArray"></app-item>

The Array

[
  {
    CREATE_TS: "2018-08-15 17:17:30.0",
    Key1: "Val1",
    Key2: "Val2",
  },
  {
    CREATE_TS: "2018-08-15 17:25:30.0",
    Key1: "Val1",
    Key2: "Val2",
  },
  {
    CREATE_TS: "2018-08-15 17:28:30.0",
    Key1: "Val1",
    Key2: "Val2",
  }
]
Huy Le
  • 491
  • 2
  • 6
  • 11

9 Answers9

33

You can use Array.sort for sort data.

I have created a demo on Stackblitz. I hope this will help/guide to you/others.

component.ts

  data = [
    {
      CREATE_TS: "2018-08-15 17:17:30.0",
      Key1: "Val1",
      Key2: "Val2",
    },
    {
      CREATE_TS: "2018-08-15 17:25:30.0",
      Key1: "Val1",
      Key2: "Val2",
    },
    {
      CREATE_TS: "2018-08-15 17:28:30.0",
      Key1: "Val1",
      Key2: "Val2",
    }
  ]

  get sortData() {
    return this.data.sort((a, b) => {
      return <any>new Date(b.CREATE_TS) - <any>new Date(a.CREATE_TS);
    });
  }

component.html

<div *ngFor="let item of sortData">
  {{item.Key1}} -- {{item.CREATE_TS}} 
</div>
Krishna Rathore
  • 9,389
  • 5
  • 24
  • 48
32

For recent first:

this.data.sort((a, b) => new Date(b.date1).getTime() - new Date(a.date1).getTime());

For OlderFirst:

this.data.sort((b, a) => new Date(b.date1).getTime() - new Date(a.date1).getTime());
Pruthvi Raj
  • 363
  • 5
  • 10
19

you can use the sort function for arrays, it takes in compare function. Parse the Date string into a date object and sort by it.

read more about here

var myArr = [


{
    CREATE_TS: "2018-08-15 17:17:30.0",
    Key1: "Val1",
    Key2: "Val2",
  },
  {
    CREATE_TS: "2018-08-15 17:25:30.0",
    Key1: "Val1",
    Key2: "Val2",
  },
  {
    CREATE_TS: "2018-08-15 17:28:30.0",
    Key1: "Val1",
    Key2: "Val2",
  }
]
myArr.sort((val)=> {return new Date(val.CREATE_TS)})

Ascending

myArr.sort((val1, val2)=> {return new Date(val1.CREATE_TS) - new 
Date(val2.CREATE_TS)})

Descending

myArr.sort((val1, val2)=> {return new Date(val2.CREATE_TS) - new 
Date(val1.CREATE_TS)})
Tiisetso Tjabane
  • 2,088
  • 2
  • 19
  • 24
  • 3
    Given the format that the timestamps are in, you don't actually need to convert them into a `Date` object. A simple string comparison (`val1.CREATE_TS > val2.CREATE_TS`) would suffice. – Simon K Aug 15 '18 at 23:07
  • 1
    @SimonK It compiled with an error because, in the sort comparison, it can not return a boolean. – Huy Le Aug 16 '18 at 02:54
  • 1
    Right, I forgot it was supposed to be a number. Go with `val1.CREATE_TS > val2.CREATE_TS ? 1 : -1` – Simon K Aug 16 '18 at 02:58
  • What if date is null or empty ? @Tiisetso – Unknown_Coder Oct 18 '18 at 12:23
16

in addition to cryptic's answer, you will likely want to wrap the sorted values in an accessor for including in the template, adding a getter in your typescript class:

public get sortedArray(): YourItemType[] {
    return this.myArr.sort(...);
}

and in the template:

<app-item *ngFor="let item of sortedArray"></app-item>

alternately, you can sort the array as you get it into your component class and store the sorted version there, however the accessor pattern can be quite useful for dynamic sorting.

derelict
  • 2,044
  • 10
  • 15
8

Using this method in Typescript, you can easily sort date values in whatever order you’d like. You can also sort any type of other data types, like number or string, by simply removing the new Date() and getTime methods.

this.data.sort((a, b) => new Date(b.CREATE_TS).getTime() - new Date(a.CREATE_TS).getTime());
Sarjerao Ghadage
  • 1,420
  • 16
  • 31
5

From looking through the docs, there doesn't seem to be any built-in array sorting. However, you can do this in your template:

<app-item *ngFor="let item of someArray.sort(sortFunc)"></app-item>

And then in your component.ts file, define the function, because you cannot define functions in your template:

sortFunc (a, b) {
  return a.CREATE_TS - b.CREATE_TS
}

Edit: Simon K pointed out that the string format allows for straight comparison without coercing to Date and then to number. My original equation (for scenarios where your date string isn't that convenient):

return new Date(a.CREATE_TS).getTime() - new Date(b.CREATE_TS).getTime()
Ben Steward
  • 2,338
  • 1
  • 13
  • 23
4

You should first parse the dates to miliseconds, then perform sorting, in order to avoid the "the left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type" typescript error when you return new Date(a.CREATE_TS) - new Date(b.CREATE_TS):

someArray.sort((a: any, b: any) => { return Date.parse(a.CREATE_TS) - Date.parse(b.CREATE_TS) });
Lucian Popa
  • 111
  • 1
  • 4
3

With moment.js you can use

const newArr = myArr.sort((a, b) => moment(b.date).unix() - moment(a.date).unix());
Suraj Parise
  • 330
  • 3
  • 18
1

For those who a researching on how to do this. I created a small type-safe array sorting method with support for deeply nested properties and Typescript autocompletion.

https://github.com/jvandenaardweg/sort-by-property

https://www.npmjs.com/package/sort-by-property

Example:

arr.sort(sortByProperty('CREATE_TS', 'asc'));