Reputation: 1484
I am very new to angular. As part of y learning, I am building a small application.
I have the following Components:
App Component - Root Component
Header Component - Displays Active Job (Based on the logged in userId), Title etc
Menu Component - Displays available Menus(ex:"Dashboard", "Set New Job","Manage Job")
Dashboard Component - Display Reports for the Active Job
SetNewJob Component - To Set a new Job as Active
ManageJob Component - To Add/Edit a few fields relevant to the job.
Dashboard, SetNewJob, and ManageJob components are loaded using router-outlet.
App.component.html
<div class='container-fluid'>
<app-header>loading</app-header>
<hr style="border: solid 1px black!important;">
<app-menu></app-menu>
<router-outlet></router-outlet>
</div>
App.component.ts - Constructor makes a service Call to find the Active Job for the user and set it as current job
import { Component,OnInit } from '@angular/core';
import { Subscriber } from '../../../../node_modules/rxjs/Subscriber';
import { Subject, Observable } from 'rxjs';
import {JobService} from '../../_services/job.service';
import { Job } from '../../_models/job';
@Component({
selector: 'app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
CurrentJob:Job
constructor(private _jobService:JobService) {
this._jobService.getUserJob(123).subscribe(job=>{
this.CurrentJob = job;
this._jobService.setCurrentJob(job);
})
}
ngOnInit() { }
}
Header.Component.ts - ngOnInit() Subscribe to the CurrentJob from the jobService and the Current Job is displayed
import { Component, OnInit, Input } from '@angular/core';
import { Subject, Observable } from 'rxjs';
import {JobService} from '../../_services/job.service';
import { Job } from '../../_models/job';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
CurrentJob:Job
constructor(private _jobService:JobService) {
}
ngOnInit() {
this._jobService.getCurrentJob().subscribe(job => { this.CurrentJob = job; });
}
}
SetNewJob.component.html
Contains a dropdown for the available jobs for the user.
on load, it should select a currently active job(ie the job which is displayed in the Header) by default.
for that, i have added below code in Constructor of SetNewJob.component.ts
this._jobService.getCurrentJob().subscribe(job => {
this.CurrentJob = job;
this.SelectedJobId=job.jobId;
});
Now the problem is when user logins, the Dashboard page will be displayed. If the User wants to Change the active job he should navigate to Set New Job. When the Navigation happens, currently active job is not Selected in Dropdown. But if the page is refreshed, Dropdown will display active Job. i.e Subscription happens only when the page refreshes.
I have tried by adding the above code (Subscription code )in ngOnInit() of SetNewJob.component.ts.
Same problem is happening in ManageJob component also. this component populates few dropdowns based on the active job. dropdown are not populated on navigation, but on page refresh every thing works fine.
Code for Job.Service.ts
import { Http, Response } from '@angular/http';
import {HttpClient} from '@angular/common/http'
import { Injectable } from '@angular/core';
import { Subject, Observable } from 'rxjs';
export const ROOT_URL:string="http://localhost:5000/api";
import 'rxjs/add/operator/map';
import {Job} from '../_models/job'
import {Area} from '../_models/area'
@Injectable()
export class JobService {
Job:Observable<Job>;
CurrentJob = new Subject<Job>();
private SelectedJob:Job;
constructor(private _http: Http,private httpClient: HttpClient){
}
getUserJob(userId:number):Observable<Job>{
return this._http.get(ROOT_URL + "/User/CurrentJob/",
{
params: {
'userId':userId.toString()
}
}
).map((res : Response) =>res.json())
.catch(this.errorHandler);
}
getCurrentJob():Observable<any>{
return this.CurrentJob.asObservable();
}
setCurrentJob(job: any) {
this.CurrentJob.next(job);
this.SelectedJob=job;
}
errorHandler(error: Response) {
return Observable.throw(error);
}
}
What is actually happening.? Why subscription is failing on route navigation.? is there any alternative for achiving this. i may need to user the currentJob object in other Pages also.
Please help.
Upvotes: 2
Views: 2290
Reputation: 11000
The issue happens because your AppComponent sets a job before your HeaderComponent subscribes to it. You can change your Subject
to BehaviorSubject
, so the last emission will be available upon subscription:
Replace this:
CurrentJob = new Subject <Job>();
Into:
CurrentJob = new BehaviorSubject<any>(null);
p.s. you can replace null
to some initial object you can show to your users. Create a default Job
class:
defaultJob: Job = { ... }
And set the initial value to the BehaviorSubject:
CurrentJob = new BehaviorSubject<Job>(this.defaultJob);
Useful to display default info if data not arrived yet and must be done to meet the requirement if you use Type custom annotation of the Subject.
Upvotes: 1