Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
280 views
in Technique[技术] by (71.8m points)

typescript - How to add active class on selected chat list item (Angular)?

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Not sure of all the logic in there, but the solution is very simple:

1- Keep a variable containing the current user (from route), which you already have => this.receiver.

2- Use [class] to add active to each element.

<li class="content" [ngClass]="{'active': chat.receiverId.username === this.receiver}">

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...