-
-
Save mdmoin7/13828acc95b3bf6c32eb98b9e7a6c581 to your computer and use it in GitHub Desktop.
/* | |
*ngFor="let c of oneDimArray | sortBy:true/false:'asc'" | |
*ngFor="let c of arrayOfObjects | sortBy:true/false:'asc':'propertyName'" | |
*/ | |
import { Pipe, PipeTransform } from "@angular/core"; | |
import { orderBy, sortBy } from "lodash"; | |
@Pipe({ name: "sortBy" }) | |
export class SortByPipe implements PipeTransform { | |
transform<T>( | |
value: T[], | |
caseInsensitive = false, | |
order = "", | |
column: string = "" | |
): T[] { | |
if (!value || order === "" || !order) { | |
return value; | |
} // no array | |
if (!column || column === "") { | |
const sorted = this.sortOnCaseSensitivity(value, caseInsensitive); | |
if (order === "asc") { | |
return sorted; | |
} else { | |
return sorted.reverse(); | |
} | |
} // sort 1d array | |
if (value.length <= 1) { | |
return value; | |
} // array with only one item | |
else { | |
const converted = this.convertMultiOnCaseSensitivity( | |
value, | |
column, | |
caseInsensitive | |
); | |
return orderBy(converted, ["sortCol"], [order]).map(v => { | |
delete v["sortCol"]; | |
return v; | |
}); | |
} | |
} | |
sortOnCaseSensitivity<T>(value: T[], caseInsensitive: boolean): T[] { | |
return sortBy(value, (v: T) => { | |
if (typeof v === "string" && caseInsensitive) { | |
return v.toLowerCase(); | |
} | |
return v; | |
}); | |
} | |
convertMultiOnCaseSensitivity<T>( | |
value: T[], | |
column: string, | |
caseInsensitive: boolean | |
): T[] { | |
let converted = value.map((v: T) => ({ ...v, sortCol: v[column] })); | |
if (caseInsensitive) { | |
converted = value.map((v: T) => { | |
if (typeof v[column] === "string") { | |
return { ...v, sortCol: v[column].toLowerCase() }; | |
} | |
return { ...v, sortCol: v[column] }; | |
}); | |
} | |
return converted; | |
} | |
} |
hey @mdmoin7, I went ahead and forked your gist and made some changes to fix the issue regarding no sort when caseInsensitive = false
. I have also changed the code to import lodash-es
, as latest Angular warns against using CommonJS or AMD modules - they prefer es modules
If you pass
caseInsensitive
asfalse
, it will not sortvalue
-'sortCol'
will not be defined in that case and will just be ignored.
@gcko can you help me with the usage Syntax as well so that I can also understand the exact behavior here and its problem and thanks for the fork.
Sure, lets look at the following sections of code:
First, the call to this.convertMultiOnCaseSensitivity
else{
const converted=this.convertMultiOnCaseSensitivity(value,column,caseInsensitive);
return orderBy(converted, ['sortCol'], [order]).map(v=>{
delete v['sortCol'];
return v;
});
}
And the function that it calls:
convertMultiOnCaseSensitivity(value:any[],column,caseInsensitive){
let converted=value;
if(caseInsensitive){
converted=value.map(v=>{
if(typeof v[column]==='string'){
return {...v,sortCol:v[column].toLowerCase()}
}
return v;
})
}
return converted;
}
The key part is that sortCol
will only be added if caseInsensitive
is a falsey value. That means when caseInsensitive = true
, in the call to orderBy
, (orderBy(converted, ['sortCol'], [order])
, the items in converted
do not have a sortItem
key.
@gcko thanks for the clarity, what i think here seems to be a problem when user doesn't provide sorting column name, correct me if I'm wrong. So in that case does placing sensitivity argument last in sequence to pipe help!!
@mdmoin7 No, the issue is the same whether or not the user passes a value to caseInsensitivity
. You can confirm this because the caseInsensitivity
is initialized as false
, so unless you pass a value of true
, it will be false
.
The issue is not related to whether the user provides a sorting column name, to be clear.
For example, the issue will appear if you do the following call:
*ngFor="let item of items|sortBy:false:'asc':'keyToSortOn';
If you pass
caseInsensitive
asfalse
, it will not sortvalue
-'sortCol'
will not be defined in that case and will just be ignored.