I have the following Angular service to parse a JSON file of messages, which works as expected, and is using an EventEmitter to send the parsed messages to a display component, which is not working as it's supposed to:
import { EventEmitter, Injectable } from '@angular/core';
import { Message } from '../models/message';
import { ParseEvent } from './parse-event';
@Injectable({
providedIn: 'root'
})
export class MessageParsingService {
public onParseComplete: EventEmitter<ParseEvent> = new EventEmitter<ParseEvent>();
public messages: Message[];
constructor() {
this.messages = [];
}
public parseJson(jsonString: string) {
let jsonObj = JSON.parse(jsonString);
this.messages = jsonObj.chats[0].messages.map((item: { timestamp: any; fromMe: any; text: any; }) => {
var msg = {
timestamp: item.timestamp,
fromMe: item.fromMe,
text: item.text,
}
this.onParseComplete.emit(new ParseEvent(msg));
return msg;
});
console.log("Messaged parsed by service: " , this.messages);
}
}
Sample JSON file I'm using for testing:
{
"chats": [
{
"contactName": "Test",
"messages": [
{
"timestamp": "2022-12-11T17:00:12Z",
"id": "35A8984427489ACE786A9F5DFA81E7",
"fromMe": true,
"type": "text",
"text": "Hello!"
},
{
"timestamp": "2022-12-11T21:34:04Z",
"id": "009715FBED647B52CD4EA6AE9A7CA4",
"fromMe": false,
"type": "text",
"text": "How are you?"
},
{
"timestamp": "2022-12-11T21:34:23Z",
"id": "479AFD522FEC7444991CCA578EDF9F",
"fromMe": false,
"type": "text",
"text": "What are you doing today?"
}
]
}
]
}
Code for the ParseEvent:
import { Message } from "../models/message";
export class ParseEvent {
message: Message;
constructor(m: Message){
this.message = m;
}
}
Component to view messages:
import { Component, OnInit } from '@angular/core';
import { Message } from '../models/message';
import { MessageParsingService } from '../services/message-parsing.service';
import { ParseEvent } from '../services/parse-event';
@Component({
selector: 'app-chat-view',
templateUrl: './chat-view.component.html',
styleUrls: ['./chat-view.component.scss']
})
export class ChatViewComponent implements OnInit {
private _serviceSubscription;
messages: Message[];
constructor(private messageParsingService: MessageParsingService) {
this.messages = [];
this._serviceSubscription = this.messageParsingService.onParseComplete.subscribe({
next: (event: ParseEvent) => {
console.log('Received message from parseEvent', event.message);
this.messages.push(event.message);
}
})
}
public logMessages(){
console.log("Log current messages: ", this.messages);
}
ngOnInit(): void {
console.log('chat view component msgs: ', this.messages);
}
}
HTML for display component:
<app-message
*ngFor="let m of messages"
[timestampInput]="m.timestamp"
[fromMeInput]="m.fromMe"
[textInput]="m.text"
>
</app-message>
<button mat-raised-button (click)="logMessages()">Log current messages</button>
In my view component, I have subscribed to the above event emitter from the parsing service. Each time an event is triggered, I am pushing the message attached to the event onto the list in ChatViewComponent.ts - I can see the messages passing through via the console.log statements, as shown in the screenshot below. However when I try and access the list from outside of the subscribe block, for example in the logMessages() button, or within ChatViewComponent.html, it returns an empty list. I tried refactoring my code to use a BehaviorSubject and Observable instead of EventEmitters, but faced the same issue where the list stays empty. I also tried changing the list in ChatViewComponent to type 'any' just in case the objects were being formatted incorrectly, but that didn't help either.
I've tried to repeat your issue however it works you can see it here https://github.com/NikBardakov/SO75195288
Maybe your issue is outside showned you code