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?
StackBlitz link:
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'; }