I am trying to send data from one routed component to another using RxJS Subject by the click of a button. The value is showing in console inside subscription but is not reflecting in the template/view.
Also, is using a subject the right way of sharing data between routed components, if not then what should I use?
home.html
<input #input placeholder="Enter something"> <button (click)="onSubmit(input.value)">Submit</button> home.ts
import { Component } from '@angular/core'; import { Router } from '@angular/router'; import { SubjectService } from '../subject.service'; @Component({ selector: 'app-home', templateUrl: './home.component.html', styleUrls: ['./home.component.css'] }) export class HomeComponent { constructor(private router: Router, private ser: SubjectService) { } onSubmit(value: string) { console.log(value); this.ser.send(value); this.router.navigate(['result']); } } result.ts
import { Component, OnInit } from '@angular/core'; import { SubjectService } from '../subject.service'; @Component({ selector: 'app-result', templateUrl: './result.component.html', styleUrls: ['./result.component.css'] }) export class ResultComponent implements OnInit { constructor(private ser: SubjectService) { } data = 'Data before it has changed'; ngOnInit(): void { console.log('result'); this.ser.source$.subscribe((message) => { this.data = message; console.log('Inside subcription:' + this.data); }); } } result.html
<p>Result page: </p> <p>Data : {{data}}</p> SubjectService.ts:
import { Injectable } from '@angular/core'; import { Subject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class SubjectService { constructor() { } private source = new Subject<any>(); source$ = this.source.asObservable(); send(message : string){ this.source.next(message); } } App.component.html
<ul> <li><a routerLinkActive="active" routerLink="/home">Home</a></li> <li><a routerLinkActive="active" routerLink="/result">Result</a></li> </ul> <p>Router Outlet: </p> <router-outlet></router-outlet> App-routing.module.ts
import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './home/home.component'; import { ResultComponent } from './result/result.component'; const routes: Routes = [ { path: 'result', component: ResultComponent }, { path: 'home', component: HomeComponent }, { path: '', redirectTo:'home', pathMatch:'full'} ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { } The data variable is not updating in the result page.
1 Answer
The problem is that you're firing the source$ observable before the results view is even initialized. If you start on your home view and enter a value you will not see the Here it is updating log in the console.
You don't really need a subject for your example, a simple service that holds your shared data in a property is plenty enough:
import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root', }) export class SubjectService { public value: string | null = null; } You can update this property by assigning it a value, e.g.
onSubmit(value: string) { this.ser.value = value; this.router.navigate(['result']); } and in your results page you can define a getter to the service variable, which will always return the current value:
public get data() { return this.ser.value || 'Value is empty'; }