We are trying to complete this chat component. When the user clicks on the left side chat item it opens messages with that chosen user. We have an active class that changes chat list item color. Trying to implement active class when the user selects any chat list item. Here is the code:
Messages service
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { Injectable,EventEmitter } from '@angular/core';
import { Message } from '@angular/compiler/src/i18n/i18n_ast';
const BASEURL = 'http://localhost:3000/api/chatapp';
@Injectable({
providedIn: 'root'
})
export class MessageService {
constructor(private http: HttpClient) {}
SendMessage(senderId, receiverId, receiverName, message): Observable<any> {
return this.http.post(`${BASEURL}/chat-messages/${senderId}/${receiverId}`, {
receiverId,
receiverName,
message
});
}
GetAllMessages(senderId, receiverId): Observable<any> {
return this.http.get(`${BASEURL}/chat-messages/${senderId}/${receiverId}`);
}
MarkMessages(sender, receiver): Observable<any> {
return this.http.get(`${BASEURL}/receiver-messages/${sender}/${receiver}`);
}
MarkAllMessages(): Observable<any> {
return this.http.get(`${BASEURL}/mark-all-messages`);
}
chatSelected = new EventEmitter<Message>();
}
Route
path: 'chat/:name',
component: MessageComponent,
canActivate: [AuthGuard]
HTML
<div id="frame">
<div id="sidepanel">
<div id="contacts" >
<ul *ngFor="let chat of chatList">
<li class="contact"
[ngClass]="{'active': chat.receiverId.username === this.selectedChat.receiverId.username}">
<div class="wrap" (click)="GoToChatPage(chat.receiverId.username)">
<span class="contact-status online"></span>
<img src="http://res.cloudinary.com/ratingapp/image/upload/v{{chat.receiverId.picVersion}}/{{chat.receiverId.picId}}" alt="" />
<div class="meta">
<p class="name">{{chat.receiverId.username}}</p>
<p class="preview">
{{chat.msgId.message[chat.msgId.message.length - 1].body.substr(0, 10)}}...</p>
</div>
</div>
</li>
</ul>
</div>
</div>
<div class="content">
<div class="contact-profile">
<img src="http://emilcarlsson.se/assets/harveyspecter.png" alt="" />
<p>Harvey Specter</p>
<div class="social-media">
<i class="material-icons">cancel</i>
</div>
</div>
<div class="messages">
<ul *ngFor="let message of messagesArray">
<li class="sent" *ngIf="user.username !== receiver && user.username !== message.sendername">
<img src="http://res.cloudinary.com/ratingapp/image/upload/v{{chat.receiverId.picVersion}}/{{chat.receiverId.picId}}" alt="" />
<p>{{message.body}}</p>
</li>
<li class="replies" *ngIf="user.username === message.sendername">
<img src="http://res.cloudinary.com/ratingapp/image/upload/v{{chat.receiverId.picVersion}}/{{chat.senderId.picId}}" alt="" />
<p>{{message.body}}</p>
</li>
</ul>
</div>
<form (ngSubmit)="SendMessage()">
<div class="message-input">
<div class="wrap">
<input [(ngModel)]="message" (keypress)="IsTyping()" type="text" placeholder="Write your message..." />
<button class="emojiBtn" (click)="Toggled()">??</button>
<div class="emoji-content-editable" (emojiPickerCaretEmitter)="HandleCurrentCaret($event)" (input)="content = $event.target.textContent"
[textContent]="content" contenteditable="true"></div>
<i class="emoji-toggle-button imgBtn" [(emojiPickerIf)]="toggled" [emojiPickerPreserveSelection]="false" [emojiPickerDirection]="direction"
[emojiPickerAutofocus]="true" (emojiPickerSelect)="HandleSelection($event)"></i>
<button class="submit"><i class="fa fa-paper-plane" aria-hidden="true"></i></button>
</div>
</div>
</form>
</div>
</div>
TypeScript
export class MessageComponent implements OnInit {
@Input() users;
receiver: string;
user: any;
message: string;
receiverData: any;
messagesArray = [];
socket: any;
typingMessage;
typing = false;
isOnline = false;
chatList = [];
public eventMock;
public eventPosMock;
public direction =
Math.random() > 0.5 ? (Math.random() > 0.5 ? 'top' : 'bottom') : Math.random() > 0.5 ? 'right' : 'left';
public toggled = false;
public content = ' ';
private _lastCaretEvent: CaretEvent;
constructor(
private tokenService: TokenService,
private msgService: MessageService,
private route: ActivatedRoute,
private usersService: UsersService
) {
this.socket = io('http://localhost:3000');
}
ngOnInit() {
this.user = this.tokenService.GetPayload();
this.route.params.subscribe(params => {
this.receiver = params.name;
this.GetUserByUsername(this.receiver);
this.socket.on('refreshPage', () => {
this.GetUserByUsername(this.receiver);
});
});
this.socket.on('is_typing', data => {
if (data.sender === this.receiver) {
this.typing = true;
}
});
this.socket.on('has_stopped_typing', data => {
if (data.sender === this.receiver) {
this.typing = false;
}
});
}
ngOnChanges(changes: SimpleChanges) {
const title = document.querySelector('.nameCol');
if (changes.users.currentValue.length > 0) {
const result = _.indexOf(changes.users.currentValue, this.receiver);
if (result > -1) {
this.isOnline = true;
(title as HTMLElement).style.marginTop = '10px';
} else {
this.isOnline = false;
(title as HTMLElement).style.marginTop = '20px';
}
}
}
ngAfterViewInit() {
const params = {
room1: this.user.username,
room2: this.receiver
};
this.socket.emit('join chat', params);
}
GetUser(id) {
this.usersService.GetUserById(id).subscribe(data => {
this.chatList = data.result.chatList;
});
}
GetUserByUsername(name) {
this.usersService.GetUserByName(name).subscribe(data => {
this.receiverData = data.result;
this.GetMessages(this.user._id, data.result._id);
});
}
GoToChatPage(chat, name) {
this.selectedChat = chat;
this.router.navigate(['chat', name]);
this.msgService.MarkMessages(this.user.username, name).subscribe(data => {
this.socket.emit('refresh', {});
});
}
GetMessages(senderId, receiverId) {
this.msgService.GetAllMessages(senderId, receiverId).subscribe(data => {
this.messagesArray = data.messages.message;
});
}
SendMessage() {
if (this.message) {
this.msgService
.SendMessage(this.user._id, this.receiverData._id, this.receiverData.username, this.message)
.subscribe(data => {
this.socket.emit('refresh', {});
this.message = '';
});
}
}
HandleSelection(event: EmojiEvent) {
this.content =
this.content.slice(0, this._lastCaretEvent.caretOffset) +
event.char +
this.content.slice(this._lastCaretEvent.caretOffset);
this.eventMock = JSON.stringify(event);
this.message = this.content;
this.toggled = !this.toggled;
this.content = '';
}
HandleCurrentCaret(event: CaretEvent) {
this._lastCaretEvent = event;
this.eventPosMock = `{ caretOffset : ${event.caretOffset}, caretRange: Range{...}, textContent: ${
event.textContent
} }`;
}
Toggled() {
this.toggled = !this.toggled;
}
IsTyping() {
this.socket.emit('start_typing', {
sender: this.user.username,
receiver: this.receiver
});
if (this.typingMessage) {
clearTimeout(this.typingMessage);
}
this.typingMessage = setTimeout(() => {
this.socket.emit('stop_typing', {
sender: this.user.username,
receiver: this.receiver
});
}, 500);
}
}
I thought adding event emitter but have no idea how will it work in this case. So how can I add active class on left chat list item when user selects a chat user from left chat list and it opens messages with that user on the right?
See Question&Answers more detail:
os