首页 > 解决方案 > 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 对象。

请帮忙。

标签: angular.net-core

解决方案


发生此问题是因为您的 AppComponent 在您的 HeaderComponent 订阅它之前设置了一个作业。您可以将您的更改SubjectBehaviorSubject,以便订阅时可以使用最后一个发射:

替换这个: CurrentJob = new Subject <Job>();

进入: CurrentJob = new BehaviorSubject<any>(null);

ps 您可以替换null为可以向用户展示的一些初始对象。创建一个默认Job类:

defaultJob: Job = { ... }

并将初始值设置为 BehaviorSubject:

CurrentJob = new BehaviorSubject<Job>(this.defaultJob);

如果数据尚未到达,则对显示默认信息很有用,如果您使用主题的类型自定义注释,则必须这样做以满足要求。


推荐阅读