I am trying to make a simple Resolve that returns a user. However, in my application, I need to wrap the http component with my own class, which returns the object as observable. My Resolver works as expected on the first user link, but when I click any user links in the UserProfileComponent after Resolve, the Resolve never exits a second time. I see the browser URL with the new ID, and console.log in UserResolve prints, but nothing happens.
My router:
import { Routes, RouterModule } from '@angular/router'; import { DashboardComponent } from './dashboard/dashboard.component'; import { UserProfileComponent } from './user-profile/user-profile.component'; import { LoginComponent } from './login/login.component'; import { AuthGuard } from './_resolve/guard.auth'; import { UserResolve } from './_resolve/user.resolve'; const appRoutes: Routes = [ { path: '', component: DashboardComponent, canActivate: [AuthGuard] }, { path: 'user/:id', component: UserProfileComponent, canActivate: [AuthGuard], resolve: { user: UserResolve } }, { path: 'login', component: LoginComponent }, // otherwise redirect to home { path: '**', redirectTo: '' } ]; export const Routing = RouterModule.forRoot(appRoutes);
UserResolve:
import { Injectable } from '@angular/core'; import { Resolve, ActivatedRouteSnapshot } from '@angular/router'; import { ApiService } from '../_services/api.service'; import { Observable } from 'rxjs'; import { User } from '../_models/user'; @Injectable() export class UserResolve implements Resolve<User> { constructor(private apiService:ApiService) {} resolve(route: ActivatedRouteSnapshot):Observable<User> { console.log('getting user ' + route.params['id'] + ' with resolver'); return this.apiService.getUser(route.params['id']).first(); } }
ApiService:
import { Injectable } from '@angular/core'; import { Http, Headers, Response, RequestOptions } from '@angular/http'; import { Observable } from 'rxjs/Observable'; import 'rxjs/Rx'; import { RefreshHttpClient } from '../_injectables/refresh-http-client'; import { User } from '../_models/user'; @Injectable() export class ApiService { constructor(private rfhttp:RefreshHttpClient) { } getUser(userId):Observable<User> { return this.rfhttp.get('/api/user?userId=' + userId); } }
And the GetreshHttpClient "get" method:
... get(url):Observable<any> { var sub = new Subject<any>(); var obs = this.http.get(url, { headers: this.createAuthorizationHeaders() }) .map(res => res.json()) .subscribe( data => { return sub.next(data); }, error => { if (error.status == 401 || error.status == 403) { this.refreshAndRetry(() => { this.http.get(url, { headers: this.createAuthorizationHeaders() }) .map(res => res.json()) .subscribe( data => { return sub.next(data); }, error => { console.error(error); return null; }); }); } else { console.error(error); return null; } } ); return sub.asObservable(); } ...
Edit: Adding a UserProfileComponent:
import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { User } from '../_models/user'; @Component({ selector: 'app-user-profile', templateUrl: './user-profile.component.html', styleUrls: ['./user-profile.component.scss'] }) export class UserProfileComponent implements OnInit { abstract:Boolean; user:User; constructor( private route:ActivatedRoute ) { } ngOnInit() { this.user = this.route.snapshot.data['user']['data']; console.log(this.user); ...
Please note that my API server returns a JSON structure with the attribute "data", therefore ['data'] .
ngOnInit in this component is not achieved with any navigation on the route, except for the first one, which makes me think that the Resolver Observable never completes.