A simple refresher. Use BehaviourSubject if you want to receive some initial / current values upon subscribing( manually in services/pipe etc, or via async pipe in html templates. Here is a basic proposal for what you are trying to achieve. Of course there is a lot more to be done considering production. Regards.
chat.service.ts:
BackEndDB : ChatMessage[] = <Obtain data for chatHistory from your DB>();
If you use any BackEnd storage for your chat history, initialize BackEndDB via that source , if not let messages$
to be new BehaviorSubject<ChatMessage[]>(null);
. This will not persist your chat history if you reload the page.
messages$ = new BehaviorSubject<ChatMessage[]> // (this.BackEndDB OR null);
sendMessage(message: ChatMessage): void {
this.BackEndDB.push(message);
this.messages$.next(this.BackEndDB);
}
getMessages(): Observable<ChatMessage[]> {
return this.messages$.asObservable();
}
and then in your component:
import {ChatService} from 'yourPath/chat.service';
@Component({
selector: 'app-chat',
templateUrl: ['./chat.component.html'],
styleUrls: ['./chat.component.css'],
})
export class ChatComponent {
inbox$: Observable<ChatMessage[]>;
constructor(private chatService: ChatService) {
this.inbox$ = this.chatService.getMessages();
}
sendMessage(username, msg) {
let message: ChatMessage = {
msg: msg,
sender: username
}
this.chatService.sendMessage(message);
}
}
and then chat.component.html:
<label> Your Name: </label>
<input type="text" #userName>
<label> Your Message: </label>
<input type="text" #userMessage>
<button type="button" (click) = "sendMessage(userName.value,userMessage.value)">Send</button>
<div *ngIf="inbox$ | async; let messages ">
<div *ngFor= "let message of messages ">
<p> {{ message.sender }} </p>
<p> said: </p>
<p> {{ message.msg }} </p>
</div>
</div>
You can create the ChatMessage Interface in a shared folder, if you are going to reuse it, or directly in your component in case it is only used there:
interface ChatMessage {
msg: string;
sender: string;
}
The only reason we push
the new messages to the BackEndDB variable and then call next on it, is because this is a simple demo. In reality you would use FirestoreCollectionDocument.valueChanges() or any other realtime data service.
Observable
andSubject
?Observable
is unicast and aSubject
is multicast. You are wrong when you saying Observables are already multicast.Subject
is both a producer and a data consumer. – Serkan Sipahi