Пишу мессенджер на Angular и столкнулся с проблемой обмена данными между компонентами, а точнее обновление данных. Есть у меня компонент ChatList:
Кликните здесь для просмотра всего текста
Javascript |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
| import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { DataStorageService } from '../data-storage.service';
import { SignalRService } from '../signal-r.service';
import { ChatService } from '../chat.service';
import { DatePipe } from '@angular/common';
@Component({
selector: 'app-chatlist',
templateUrl: './chatlist.component.html',
styleUrls: ['./chatlist.component.css']
})
export class ChatlistComponent implements OnInit {
chats:Chat[] = [];
selectedChat: Chat | null = null;
searchForm: FormGroup;
searchResults: any[] = [];
chatblockheight: number = 85;
addpanelheight: number = 6;
isAddPanelOpen: boolean = false;
isChatCreateErrorMsgVisible: boolean = false;
ChatCreateErrorMsg: string = '';
userDefaultImg = 'https://cdn-icons-png.flaticon.com/512/3607/3607444.png';
constructor(private fb: FormBuilder, private dataService: DataStorageService, private signalrService: SignalRService, private chatService: ChatService) {
this.searchForm = this.fb.group({
username: ['', Validators.required]
});
}
ngOnInit(): void {
this.loadChats();
this.signalrService.chatUpdate$.subscribe((message) => {
this.loadChats();
});
}
loadChats() {
this.dataService.getChats().subscribe(
(result) => {
this.chats = result.map(chat => ({
chatId: chat.chatId,
otherUserImg: chat.otherUserImg,
otherUserName: chat.otherUserName,
lastMessage: chat.lastMessage,
lastMessageDate: chat.lastMessageDate
}))
},
(error) => {
console.log('dataservice.getchats error');
}
);
}
openAddPanel() {
this.isAddPanelOpen = true;
this.chatblockheight = 50;
this.addpanelheight = 41;
}
closeAddPanel() {
this.isAddPanelOpen = false;
this.chatblockheight = 85;
this.addpanelheight = 6;
}
searchUsers() {
const username = this.searchForm.get('username')?.value;
if(username) {
this.dataService.searchUsersByNickname(username).subscribe(
(results) => {
this.searchResults = results;
},
(error) => {
}
);
}
}
createChat(userid: number) {
this.dataService.createChat(userid).subscribe(
(result) => {
this.loadChats();
console.log('createChatincomponent');
},
(error) => {
console.log(error.error);
this.isChatCreateErrorMsgVisible = true;
this.ChatCreateErrorMsg = error.error;
}
);
}
onChatClick(chat: Chat): void {
this.selectedChat = chat;
this.chatService.setSelectedChat(chat);
}
}
export class Chat {
chatId: string = '';
otherUserName: string = '';
lastMessage: string = '';
otherUserImg: string = '';
lastMessageDate: string = '';
} |
|
Представление:
Кликните здесь для просмотра всего текста
HTML5 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
| <div class="chat-block" [style.height.vh]="chatblockheight">
<ul>
<li *ngFor="let chat of chats">
<div class="chat-container" [ngClass]="{selectedChat: chat === selectedChat}" (click)="onChatClick(chat)">
<img [src]="chat.otherUserImg">
<div class="chat-details">
<h3>{{chat.otherUserName}}</h3>
<p>{{chat.lastMessage}}</p>
</div>
<div class="time-message">
<p>{{chat.lastMessageDate | date:'medium'}}</p>
</div>
</div>
</li>
</ul>
</div>
<div class="addchat-panel" [style.height.vh]="addpanelheight">
<div *ngIf="!isAddPanelOpen" class="closed-div">
<button class="open-button" (click)="openAddPanel()">Create new chat</button>
</div>
<div *ngIf="isAddPanelOpen" class="opened-div">
<div class="close-button-container">
<button class="close-button" (click)="closeAddPanel()">×</button>
</div>
<label class="search-label">Search user</label>
<div class="searchform-div">
<form [formGroup]="searchForm">
<input class="search-input" type="text" id="username" formControlName="username" placeholder="Input username here...">
<button class="formsearch-button" (click)="searchUsers()">search</button>
</form>
</div>
<label class="results-label">Results:</label>
<div class="searchresults-div">
<div *ngFor="let result of searchResults">
<div class="result-container">
<img class="result-userimg" [src]="result.userimgurl ? result.userimgurl : userDefaultImg">
<p class="result-p">{{result.username}}</p>
<button class="createchat-button" (click)="createChat(result.userid)">Create chat</button>
</div>
</div>
</div>
<div *ngIf="isChatCreateErrorMsgVisible" class="errorMsgDiv">
<p>{{ChatCreateErrorMsg}}</p>
</div>
</div>
</div> |
|
И второй компонент ChatView:
Кликните здесь для просмотра всего текста
Javascript |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
| import { ChangeDetectorRef, Component, OnDestroy } from '@angular/core';
import { ChatService } from '../chat.service';
import { Chat } from '../chatlist/chatlist.component';
import { DataStorageService } from '../data-storage.service';
import { Subscription } from 'rxjs';
@Component({
selector: 'app-chatview',
templateUrl: './chatview.component.html',
styleUrls: ['./chatview.component.css']
})
export class ChatviewComponent implements OnDestroy {
selectedChat: Chat | null = null;
messages: Message[] = [];
private chatSubscription: Subscription;
userDefaultImg = 'https://cdn-icons-png.flaticon.com/512/3607/3607444.png';
constructor(private chatService: ChatService, private dataService: DataStorageService) {
this.chatSubscription = this.chatService.getSelectedChat().subscribe((chat) => {
console.log('Selected Chat Updated:', chat);
this.selectedChat = chat;
console.log(this.selectedChat?.otherUserImg);
console.log(this.selectedChat?.otherUserName);
//this.getMessages(); // Загрузка сообщений при изменении чата
});
}
ngOnDestroy(): void {
this.chatSubscription.unsubscribe();
}
getMessages() {
if (this.selectedChat) {
this.dataService.getMessages(this.selectedChat.chatId).subscribe(
(result) => {
this.messages = result;
},
(error) => {
console.error(error);
}
);
}
}
}
export class Message {
messageId: string = '';
userId: number = 0;
userName: string = '';
content: string = '';
date: string = '';
} |
|
Представление:
Кликните здесь для просмотра всего текста
<div class="chatview-container">
<div class="head" *ngIf="selectedChat">
<img class="imguser" [src]="selectedChat.otherUserImg" alt="non"/>
<p class="username">{{selectedChat.otherUserName}}</p>
</div>
<div class="head" *ngIf="!selectedChat">
<img class="imguser" [src]="userDefaultImg" alt="non"/>
<p class="username">Username</p>
</div>
<div class="message-container">
<p>puk</p>
</div>
<div class="message-writter">
<input class="inputmessage" type="text" placeholder="Input message..."/>
<button class="send-btn">
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRAJ7Get2YkUhisLi7eQ8HqlShRDI4T9A4QSxjvmA5bkg&s" class="send-button-img"/>
</button>
</div>
</div>
В первом компоненте у меня есть массив чатов:
Javascript |
1
| messages: Message[] = []; |
|
Список которых отображён в представлении, где при нажатии на определенный чат, он передается через сервис во второе представление:
Кликните здесь для просмотра всего текста
HTML5 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| <ul>
<li *ngFor="let chat of chats">
<div class="chat-container" [ngClass]="{selectedChat: chat === selectedChat}" (click)="onChatClick(chat)">
<img [src]="chat.otherUserImg">
<div class="chat-details">
<h3>{{chat.otherUserName}}</h3>
<p>{{chat.lastMessage}}</p>
</div>
<div class="time-message">
<p>{{chat.lastMessageDate | date:'medium'}}</p>
</div>
</div>
</li>
</ul> |
|
Метод который передает:
Кликните здесь для просмотра всего текста
Javascript |
1
2
3
4
| onChatClick(chat: Chat): void {
this.selectedChat = chat;
this.chatService.setSelectedChat(chat);
} |
|
Сервис:
Кликните здесь для просмотра всего текста
Javascript |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { Chat } from './chatlist/chatlist.component';
@Injectable({
providedIn: 'root'
})
export class ChatService {
private selectedChatSubject: BehaviorSubject<Chat | null> = new BehaviorSubject<Chat | null>(null);
$selectedChat: Observable<Chat | null> = this.selectedChatSubject.asObservable();
setSelectedChat(chat: Chat): void {
this.selectedChatSubject.next(chat);
}
getSelectedChat() : Observable<Chat | null> {
return this.$selectedChat;
}
} |
|
Место получения во втором компоненте:
Кликните здесь для просмотра всего текста
Javascript |
1
2
3
4
5
6
7
8
| constructor(private chatService: ChatService, private dataService: DataStorageService) {
this.chatSubscription = this.chatService.getSelectedChat().subscribe((chat) => {
console.log('Selected Chat Updated:', chat);
this.selectedChat = chat;
console.log(this.selectedChat?.otherUserImg);
console.log(this.selectedChat?.otherUserName);
});
} |
|
Но в представлении не выводится выбранный чат:
Кликните здесь для просмотра всего текста
HTML5 |
1
2
3
4
5
6
7
8
| <div class="head" *ngIf="selectedChat">
<img class="imguser" [src]="selectedChat.otherUserImg" alt="non"/>
<p class="username">{{selectedChat.otherUserName}}</p>
</div>
<div class="head" *ngIf="!selectedChat">
<img class="imguser" [src]="userDefaultImg" alt="non"/>
<p class="username">Username</p>
</div> |
|
А в консоль выводит следующее:
Кликните здесь для просмотра всего текста
Javascript |
1
2
3
4
| console.log('Selected Chat Updated:', chat);
this.selectedChat = chat;
console.log(this.selectedChat?.otherUserImg);
console.log(this.selectedChat?.otherUserName); |
|
Selected Chat Updated: ObjectchatId: 3lastMessage: nulllastMessageDate: nullotherUserImg: nullotherUserName: null[[Prototype]]: Object
chatview.component.ts:23 null
chatview.component.ts:24 null
Подскажите как решить проблему