
Existing member? Log in and continue learning

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

Unlock full course by purchasing a membership
Adding Live Chat Messages
Adding Live Chat Messages
Currently, the only way we can add new messages to our Firestore database is to do it manually through the emulator interface. In this lesson, we are going to provide a way to do it through the application.
Update the MessageService
import { Observable, defer, merge } from 'rxjs';import { collection, query, orderBy, limit, addDoc } from 'firebase/firestore';
private addMessage(message: string) { const newMessage: Message = { content: message, created: Date.now().toString(), };
const messagesCollection = collection(this.firestore, 'messages'); return defer(() => addDoc(messagesCollection, newMessage)); }
An important thing to note here as that we are just using [email protected]
as the
author since we don’t have a login system/user authentication yet — we will need
to come back to this method later to use the user’s actual email.
Just like with the getMessages
example, we create a reference to the
collection we are interested in:
const messagesCollection = collection(this.firestore, 'messages');
But this time, we use the addDoc
method from firebase
to add the new
document we just created to the messages
collection. Note that we do not have
to supply an id
for our documents as this is created automatically by Firestore.
Also notice that we are wrapping the call to addDoc
in defer
. This is
because addDoc
returns a Promise. We want to convert this into an
Observable
. We can use from
from RxJS to do this, but the benefit of using
defer
is that addDoc
will be executed lazily.
The general idea is that Promises are executed eagerly/immediately. Even if you
are not using the result, the code in a Promise (e.g. adding a document to
Firebase in this case) will be executed immediately. This is different to an
observable which is lazy — an observable won’t execute any code until we
subscribe
to it.
You might think that since from
can convert a Promise
to an Observable
that it would make it lazy. However, if we use from
the Promise
will still
be executed immediately, even if we don’t subscribe to it. Often this won’t
cause any problems, but just to be safe, we will generally always use defer
so
that it will function in the way we expect: no code gets executed until we
subscribe to the observable.
Now we are going to add our source for handling adding messages.
add$ = new Subject<Message['content']>();
We’re using that TypeScript trick again here so that we can use the type of
whatever content
is in our Message
interface for our source.
Now we are going to make use of that concept we talked about in the advanced state management module.
constructor() { // reducers const nextState$ = merge( this.messages$.pipe(map((messages) => ({ messages }))), this.add$.pipe( exhaustMap((message) => this.addMessage(message)), ignoreElements(), catchError((error) => of({ error })) ) );
connect(this.state).with(nextState$); }
Remember how we aren’t actually interested in setting the values from the add$
source in our state. The whole point of the add$
source is just to trigger the
addMessage
method. It is the addMessage
method that will cause data to be
added to Firestore, which will then also automatically cause our messages$
source to emit with the new data, and that is how the data gets set in our
state.
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).