Launch sale! Get 30% OFF expires in 126:46:23

Existing member? Log in and continue learning

See if you like it, start the course for free!

Unlock full course by purchasing a membership
Creating a Messages Service to Interact with Firestore
Creating a Messages Service to Interact with Firestore
Once again, our usual approach is to start with the “main” feature of the application. Although we will eventually have things like login and account creation, the main purpose of our application is creating and displaying messages. Let’s start there.
Create an Interface for messages
export interface Message { author: string; content: string; created: string;}
Creating the Message Service
import { Injectable, computed, inject, signal } from '@angular/core';import { Observable, merge } from 'rxjs';import { collection, query, orderBy, limit } from 'firebase/firestore';import { collectionData } from 'rxfire/firestore';import { map } from 'rxjs/operators';import { connect } from 'ngxtension/connect';
import { Message } from '../interfaces/message';import { FIRESTORE } from '../../../main';
interface MessageState { messages: Message[]; error: string | null;}
@Injectable({ providedIn: 'root',})export class MessageService { private firestore = inject(FIRESTORE);
// sources messages$ = this.getMessages();
// state private state = signal<MessageState>({ messages: [], error: null, });
// selectors messages = computed(() => this.state().messages); error = computed(() => this.state().error);
constructor() { // reducers const nextState$ = merge( this.messages$.pipe(map((messages) => ({ messages }))) );
connect(this.state).with(nextState$); }
private getMessages() { const messagesCollection = query( collection(this.firestore, 'messages'), orderBy('created', 'desc'), limit(50) );
return collectionData(messagesCollection, { idField: 'id' }).pipe( map((messages) => [...messages].reverse()) ) as Observable<Message[]>; }}
Once again we have our basic state management setup, except this time we are
using the connect
function that we covered in the advanced state management
module.
To quickly recap, this is essentially the same idea as our normal reducers that we have been creating:
constructor() { // reducers const nextState$ = merge( this.messages$.pipe(map((messages) => ({ messages }))) );
connect(this.state).with(nextState$); }
Except rather than subscribing and calling state.update
with the source
values, instead we map
those values and return an object with whatever values
we want to set in the state. In this case, we return { messages }
because we
want to update the messages
property in our state signal with the messages
emitted on the messages$
stream.
Notice that we are also already integrating with Firestore now and making
use of our injection token by injecting FIRESTORE
as this.firestore
:
private getMessages() { const messagesCollection = query( collection(this.firestore, 'messages'), orderBy('created', 'desc'), limit(50) );
return collectionData(messagesCollection, { idField: 'id' }).pipe( map((messages) => [...messages].reverse()) ) as Observable<Message[]>; }
We are using some functions from both the firebase
and rxfire
libraries in
order to retrieve documents from a specific collection in our Firestore
database. Let’s walk through what is happening step-by-step here:
Thanks for checking out the preview of this lesson!
You do not have the appropriate membership to view the full lesson. If you would like full access to this module you can view membership options (or log in if you are already have an appropriate membership).