I have created a service which has a subject named selectedNode. I am trying to update the value of subject when I gives direct URL for loading a page. The issue is that the value of Subject is not updated when I tries to update the value directly when passing the URL.
e.g. if I opens URL localhost:4200/blog/page/subpage
it should update selectedNode with value page/subpage
. But, it does not.
My code is as below:
blog.component.ts
import {Component, OnInit} from '@angular/core';
import {BlogService} from '../../services/blog.service';
import {Router} from '@angular/router';
@Component({
selector: 'app-blog',
templateUrl: './blog.component.html',
styleUrls: ['./blog.component.css']
})
export class BlogComponent implements OnInit {
constructor(private blogService: BlogService, private router: Router) {
}
ngOnInit() {
let routerURL = this.router.url;
routerURL = routerURL.replace('/blog/', '');
console.log(routerURL);
this.blogService.selectedNode.next(routerURL);
}
}
Here the below code does not update the SelectedNode Subject. I checked while debug. The value is not updated in Subject despite of routerURL has a different value and the this.blogService.selectedNode.next(routerURL);
is also called.
my blog.service.ts file is as follows:
import {Injectable} from '@angular/core';
import {Subject} from 'rxjs';
import {HttpClient} from '@angular/common/http';
@Injectable()
export class BlogService {
public selectedNode: Subject<string> = new Subject<string>();
public sideNavDisabled: Subject<boolean> = new Subject<boolean>();
constructor(private http: HttpClient) {
}
public getTreeNodes() {
return this.http.get('/assets/tree.json');
}
public getPageContent(page: string) {
return this.http.get('/assets/TreeStructure/' + page + '.html');
}
}
My complete code is present at https://github.com/vibhorgoyal18/atest-blog and can be viewed on https://stackblitz.com/github/vibhorgoyal18/atest-blog
Firstly, thanks for putting your code in stackblitz. This helped me understand the problem a lot faster! That is the reason I upvoted, and am answering your question.
The issue is that the value of Subject is not updated when I tries to update the value directly when passing the URL.
It is in fact updated. To prove this, replace the ngOnInit
method of BlogComponent
with the following code:
const routerURL = this.router.url;
this.blogService.selectedNode.subscribe(console.log); // console.log is called here
this.blogService.selectedNode.next(routerURL);
The problem arises from the fact that the subscriptions are not initiated before the Subject
'snext
method is called. The components that are subscribing to the Subject
aren't instantiated before this method is called.
If you want to emit a value to a Subject
and have it's future observables get that value regardless of what is subscribed to to the Subject
at the time of emission, have a look at the ReplaySubject
Before taking a look atReplaySubject
s though, it is good to understand the difference between hot and cold observables: Subjects are 'hot' observables, which mean they fire regardless of what is subscribed to them. On the contrary, 'cold' observables are they fired dependent of what is subscribed to them. See here for more information.