Search code examples
angularserviceroutercommunication

Angular Communicating from app component to a route


I am working on an Angular project with routing. I am already communicating from a route to the app component and updating its value there. However, when I try to send that information to another route (that may not be showing in the browser), I cannot access it. I just need this information in that particular route and would go with any method that can get this done.

In the app.component.ts I have

import { Component, OnInit, OnDestroy } from '@angular/core';
import { RouterModule } from '@angular/router';
import { Subscription } from 'rxjs';
import { MessageService } from './message.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent implements OnInit, OnDestroy{
public message = "Discover Workouts";
public state:boolean = false; 

subscription: Subscription;
  
  //Inject MessageService
  constructor(private messageService: MessageService) {
    this.subscription = this.messageService.getMessage()
      .subscribe(mymessage => this.message = mymessage)
  }
ngOnInit(){
}
  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

In workout-options.ts I have this

import { Component, Output, EventEmitter,  OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { MessageService } from '../message.service';
import { Sio2service } from '../sio2.service';

@Component({
  selector: 'app-workout-options',
  templateUrl: 'workout-options.component.html',
  styleUrls: ['../app.component.css']
})
export class WorkoutOptionsComponent implements OnDestroy{
mymessage: string;
subscription: Subscription;

@Output() public childEvent = new EventEmitter();
  constructor(private messageService: MessageService) {
this.subscription = this.messageService.getMessage()
.subscribe(mymessage => { this.mymessage = mymessage; });
}

OnInit(){
 }
 
FupdateParent(exerName:string) {
    this.messageService.updateMessage(exerName);
//  this.sio2.sendMsg(exerName);
//console.log(exerName);
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

and in the message.service, I have

import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
 
@Injectable({ providedIn: 'root' })
export class MessageService {
    private myMessage = new Subject<string>();
 
    updateMessage(message: string) {
        this.myMessage.next(message);
    }
 
    clearMessage() {
        this.myMessage.next();
    }
 
    getMessage(): Observable<string> {
        return this.myMessage.asObservable();
    }
}

This far everything works fine. But when I try to receive in start-workout.ts (which is implemented as a route) the value sent by the latter component (which is also implemented as a route), I cannot.

Here is what I have tried.

In the start-workout.component.ts I have this (portion of the code)

export class StartWorkoutComponent implements OnInit{
public message = "";
subscription: Subscription;

  constructor(private messageService: MessageService, private httpClient: HttpClient){
this.subscription = this.messageService.getMessage()
.subscribe(mymessage => { this.message = mymessage; });
}

ngOnDestroy() {
  this.subscription.unsubscribe();
}

I have to be doing something wrong. Could someone please guide me


Solution

  • The problem is here

    private myMessage = new Subject<string>();
    

    Subject only fire to the those subscriptions which are subscribed at the time of firing the event. In order to get the data in the other route you have to change the message to ReplaySubject which provides the value everyone no matter when the subscription occures.

    Check out RXJS documentation for more info about Subjects and ReplaySubjects

    solution: change message service

    export class MessageService {
    private myMessage = new ReplaySubject<string>();
    
    updateMessage(message: string) {
        this.myMessage.next(message);
    }
    
    clearMessage() {
        this.myMessage.next();
    }
    
    getMessage(): Observable<string> {
        return this.myMessage.asObservable();
    }
    

    }