Is there a way to keep a reference of the same collection, but change the ordering using firestore?
TLDR: This is like the functionality I'm trying to achieve: https://stackoverflow.com/a/17320018, but since my data is from firestore, I haven't quite figured out the correct way to accomplish this dynamically.
Say I have a messagesService.ts
which contains a collection of messages and a reference to an Observable of messages:
messagesCollection: AngularFirestoreCollection<Message>
messages: Observable<Message[]>;
this.messagesCollection = this.db.collection('messages', ref => {
return ref.orderBy('dateCreated', 'desc');
});
this.messages= this.messagesCollection.valueChanges();
When I pop this data into an *ngFor="let message of messages | async"
it displays the newest messages on top as expected.
Where I need help:
I'd like to be able to click a button and change the ordering of the messages (or the ordering of the data I get from firestore). For example, you could click a button to sort by messages with the most likes, or highest views, or the oldest messages, alphabetical, etc. Do I need to have a separate reference for every single way I want to sort the same collection? That seems sloppy, is there a cleaner way to do this dynamically?
Initially, I tried something like this:
sortMessagesBy(field) {
this.messagesCollection = this.db.collection('messages', ref => {
return ref.orderBy(field, 'desc');
});
}
However, this didn't work because it seemed to change the reference to the collection, so the messages observable wasn't updated.
So next, I tried this:
sortMessagesBy(field) {
this.messagesCollection = this.db.collection('messages', ref => {
return ref.orderBy(field, 'desc');
});
this.messages= this.messagesCollection.valueChanges();
return this.messages;
}
but this seems to create a new this.messages object which makes ngFor re-render the entire page and looks super sloppy (even when using trackBy).
Eventually, I'd like to narrow things down further, in the same collection where I may even have a where clause to target a specific subset of messages and be able to apply the same dynamic sorting too, I.E.:
this.messagesCollection = this.db.collection('messages', ref => {
return ref.where("type", "==", "todo").orderBy(field, 'desc');
});
and I just don't see how I could do this without figuring out how to do it dynamically.