I have an interesting problem (I think) and would love some help.
I am returning an Observable[DisplayCard[]] that is filtered based on a value. That all works great. After I filter that array based on a value, I NOW want to sort the returned array by another one of it's values called category
. category
can only be one of three String values: ONGOING
, UPCOMING
, and PAST
.
I want to return an array that will sort like this: ONGOING --> UPCOMING --> PAST. So, all the display cards that have "ONGOING" will be in front, after there is no more of those, I want all the "UPCOMING" cards and then after those, I want all the "PAST" cards to show.
Here is my code:
displayCommunityCards$ = this.cardService.displayCards$
.pipe(
map(communityEventsCards => communityEventsCards.filter(community => community.type === 'COMMUNITY EVENT')
.sort((a, b) => {
return ???
}),
tap(data => console.log('Community Cards: ', JSON.stringify(data))),
);
You can achieve this by creating an enum to represent all possible values for CardCategory
and defining the order they should be sorted in using Record<CardCategory, number>
:
export enum CardCategory {
OnGoing = 'ONGOING',
Upcoming = 'UPCOMING',
Past = 'PAST',
}
export const CategorySortOrder: Record<CardCategory, number> = {
'ONGOING' : 0,
'UPCOMING' : 1,
'PAST' : 2
}
Then create a sort function that uses that to sort:
function sortByCardCategory(a: DisplayCard, b: DisplayCard) {
if(a.category === b.category) return 0;
return CategorySortOrder[a.category] > CategorySortOrder[b.category] ? 1 : -1;
}
You can now easily sort like this:
displayCommunityCards$ = this.cardService.displayCards$.pipe(
map(cards => cards
.filter(c => c.type === CardType.CommunityEvent)
.sort(sortByCardCategory)
)
);
Here's a working StackBlitz demo.
Using the Record
type isn't completely necessary, but it does guarantee that you define a sort order for all values of CardCategory
. For example, if you added a new CardCategory
, typescript will throw an error about CategorySortOrder
not defining all values of CardCategory
.
Property 'MYNEWCAT' is missing in type
'{
UPCOMING: number;
ONGOING: number;
PAST: number;
}'
but required in type 'Record<CardCategory, number>'. (2741)