angular - Angular 4 observable - 订阅不适用于路线导航,但适用于页面刷新
问题描述
我对角度很陌生。作为学习的一部分,我正在构建一个小型应用程序。
我有以下组件:
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 和 ManageJob 组件使用 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 - 构造函数调用服务以查找用户的活动作业并将其设置为当前作业
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() 从 jobService 订阅 CurrentJob 并显示当前 Job
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;
});
现在的问题是当用户登录时,将显示仪表板页面。如果用户想要更改活动作业,他应该导航到设置新作业。发生导航时,当前活动的作业未在下拉列表中选择。但是如果页面被刷新,Dropdown 会显示活动 Job。即订阅仅在页面刷新时发生。
我尝试在 SetNewJob.component.ts 的 ngOnInit() 中添加上述代码(订阅代码)。
同样的问题也发生在 ManageJob 组件中。此组件根据活动作业填充几个下拉列表。导航上没有填充下拉菜单,但在页面刷新时一切正常。
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);
}
}
到底发生了什么。?为什么订阅在路线导航上失败。?有没有其他方法可以实现这一目标。我可能还需要在其他页面中使用 currentJob 对象。
请帮忙。
解决方案
发生此问题是因为您的 AppComponent 在您的 HeaderComponent 订阅它之前设置了一个作业。您可以将您的更改Subject
为BehaviorSubject
,以便订阅时可以使用最后一个发射:
替换这个:
CurrentJob = new Subject <Job>();
进入:
CurrentJob = new BehaviorSubject<any>(null);
ps 您可以替换null
为可以向用户展示的一些初始对象。创建一个默认Job
类:
defaultJob: Job = { ... }
并将初始值设置为 BehaviorSubject:
CurrentJob = new BehaviorSubject<Job>(this.defaultJob);
如果数据尚未到达,则对显示默认信息很有用,如果您使用主题的类型自定义注释,则必须这样做以满足要求。
推荐阅读
- javascript - 呃!使用 npm run build 在 Vue 中构建用于生产的代码
- javascript - Sequelize Mock 不能与 Sequelize 函数“count”一起正常工作
- kubernetes - Kubernetes - 请求 CPU 和限制 CPU 问题
- android - 如何播放应用文件夹中的音频文件?
- r - R:光栅化具有复杂权重的多边形
- sql - 将 MAX_BY 函数转换为 Oracle SQL
- flutter - 有没有办法手动启动和停止流?
- python - 获取 MAE 和 RMSE
- javascript - Chrome 阻止重定向到扩展页面
- javascript - 使用对象数组查找数组的索引