menu

Questions & Answers

Angular subscription not saving data

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.

enter image description here

Answers(1) :

I've tried to repeat your issue however it works you can see it here https://github.com/NikBardakov/SO75195288

Console

Maybe your issue is outside showned you code