1

I have implemented reusable sorting function,sorting by number and text are working fine,But it fails for sort by date.

orderBy(array: Array<any>, fieldName: string, direction: string) {
  return array.sort((a, b) => {
    let objectA: number|string = '';
    let objectB: number|string = '';
    [objectA, objectB] = [a[fieldName], b[fieldName]];
    let valueA = isNaN(+objectA) ? objectA.toString().toUpperCase() : +objectA;
    let valueB = isNaN(+objectB) ? objectB.toString().toUpperCase() : +objectB;
    return (valueA < valueB ? -1 : 1) * (direction == 'asc' ? 1 : -1);
  });
}

how to sort by date, text numbers and special char.

Gopalakrishnan
  • 957
  • 8
  • 19

3 Answers3

1

try this:

orderBy(array: Array<any>, fieldName: string, direction: string) {
  return array.sort((a, b) => {
    let objectA: number|string|Date = '';
    let objectB: number|string|Date = '';
    [objectA, objectB] = [a[fieldName], b[fieldName]];

    // I assume that objectA and objectB are of the same type
    return typeof objectA === 'string' ? objectA.localeCompare(objectB) : objectA - objectB;
  });
}

if Date type is not recognized, you may need to add es6 entry to your compilerOptions, see this answer for more details

UPDATE

If all your values to be sorted are strings try this:

orderBy(array: Array<any>, fieldName: string, direction: string) {
  return array.sort((a, b) => {
    let objectA: number|string|Date = '';
    let objectB: number|string|Date = '';
    // map function here will convert '15/12/2018' into '2018/12/15'
    // so we can compare values as strings, numbers and strings
    // will remain unchanged
    [objectA, objectB] = [a[fieldName], b[fieldName]].map(i => i.split('/').reverse().join('/'));

    return isNaN(+objectA) ? objectA.localeCompare(objectB) : +objectA - +objectB;
  });
}
Andriy
  • 14,781
  • 4
  • 46
  • 50
  • "objectA.localeCompare(objectB) : objectA - objectB;" gives an error.. not working – Gopalakrishnan Mar 14 '18 at 07:03
  • if objectA and objectB are strings, this should work. try `'aaa'.localeCompare('ddd')` in debugger console of your browser. Maybe objectA or objectB are not strings in your case? But it should yield an error because of typescript `Date` type. please create Plunker or stackblitz with your array and code and I will try to help. see also https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare – Andriy Mar 14 '18 at 07:08
  • which error gives you "objectA.localeCompare(objectB) : objectA - objectB;"? – Andriy Mar 14 '18 at 08:51
0

I think this could be best since the localCompare function returns positive for after and negatives for before and 0 for equals (in this example I'm comparing .name wich is an atribute of objects a and b that are in this.array)

this.array.sort((a, b) => { 
 return a.name.localeCompare(b.name);
});
-1

if you are using type script than you can do like this , havent tried but you can tryout

public orderby(fieldName : string)
{
    switch (typeof obj[fieldName].constructor.name) {           
            case "String":
                array.sort();
            case "Number":
                  array.sort(function(a,b){
                       return a-b);
                 });
            case "Date"://you can check type and add accordingly 
            //as suggested by @Andriy  its going to be object 
                 array.sort(function(a,b){
                       return new Date(b.date) - new Date(a.date);
                 });
            default:
                throw new Error("Type of T is not a valid return type!");
        }
    } else {
        throw new Error("Key '" + key + "' does not exist!");
    }
}

for date sorting i do like this , converting values in date and get value for minus operation which returns zero, plus or negative vlaue

array.sort(function(a,b){
  return new Date(b.date) - new Date(a.date);
});
Pranay Rana
  • 175,020
  • 35
  • 237
  • 263
  • this will sort only date column. I need text and numbers too. dynamic columns and values. – Gopalakrishnan Mar 14 '18 at 06:23
  • @Gopalakrishnan - so you need generic method ?? – Pranay Rana Mar 14 '18 at 06:26
  • @Gopalakrishnan - so you are using typescript ?? – Pranay Rana Mar 14 '18 at 06:28
  • yeah. calling this function as service – Gopalakrishnan Mar 14 '18 at 06:30
  • @Gopalakrishnan - you can tryout solution may work for you – Pranay Rana Mar 14 '18 at 06:40
  • `typeof new Date()` is `object`, not `date` – Andriy Mar 14 '18 at 06:41
  • @Andriy - got your point , havent tried this but just for suggestion i gave option, but updated my answer as you suggested – Pranay Rana Mar 14 '18 at 06:45
  • there is no JS type `date` (https://developer.mozilla.org/he/docs/Web/JavaScript/Data_structures#Data_types). But you can always check constructor's name: `switch (obj[fieldName].constructor.name)`, which should return `Number`, `String` or `Date` – Andriy Mar 14 '18 at 06:50
  • @Pranay Not working. (typeof obj[fieldName].constructor.name) gives string for all columns even number, date column in console. – Gopalakrishnan Mar 14 '18 at 07:01
  • @Gopalakrishnan - if it gives string value for all than you should convert type accordingly ...like for number you can try `parseint` and string to date by doing parsing of string – Pranay Rana Mar 14 '18 at 07:19
  • your date field is actually a string, not a date object, all your fields are strings, according to your comment. You should consider using converting to Date or Number prior to sorting, – Andriy Mar 14 '18 at 07:23
  • `typeof obj[fieldName].constructor.name` will always return 'string', because constructor's name's type is a string. It should be just `switch (obj[fieldName].constructor.name)` – Andriy Mar 15 '18 at 21:39