Angular2 router with Http data service through 404 observable capture solution

In my Guard solution, I get an Http Observable to return the user JSON from a specific id .

I want to catch the error and redirect to the user review if id does not exist. I saw code that solves this with a promise, but not with the observable. I would like to see a solution with Observable!

I am currently getting "EXCEPTION: Uncaught (in promise): Response with status: 404 Not Found for URL: http://127.0.0.1:3000/users/191" , as user 191 is not exsist.

Here is my code:

Resolve:

 import { Injectable } from '@angular/core'; import { Resolve, ActivatedRouteSnapshot, ActivatedRoute } from '@angular/router'; import { UsersService } from '../shared/services/users.service'; import { User } from '../shared/models/user'; @Injectable() export class UserResolveService implements Resolve<User> { user: User; constructor(private service: UsersService) {} resolve(route: ActivatedRouteSnapshot) { let id = route.params['id']; // getUser returns an Http Observable return this.service.getUser(id); // ERROR HANDLING IF id DOES NOT EXIST // REROUTE TO USER OVERVIEW // A TUTORIAL WITH PROMISE USES FOLLOWING CODE // .then(user => { // if (user) { // return user; // } else { // // navigate the user back to the users page // this.router.navigate(['/users']); // return false; // } // }); } } 

UsersService getUser (id):

 import { Injectable } from '@angular/core'; import { Http } from '@angular/http'; import { environment } from "../../../environments/environment"; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/catch'; @Injectable() export class UsersService { private _url = environment.RAILS_API_BASE_URL+"/users"; constructor(private http :Http) { } ... getUser(userId){ return this.http.get(this.getUserUrl(userId)) .map(res => res.json()) } ... private getUserUrl(userId){ return this._url + "/" + userId; } } 

user.routing.ts:

 import { Routes, RouterModule } from '@angular/router'; import { ModuleWithProviders } from '@angular/core'; import { UsersResolveService } from './users-resolve.service'; import { UserResolveService } from './user-resolve.service'; import { UsersComponent } from './users.component'; import { UserDetailComponent } from './user-detail.component'; import { UserSectionComponent } from './user-section.component'; const userRoutes: Routes = [ { path: '', component: UserSectionComponent, children: [ { path: ':id', component: UserDetailComponent, resolve: { user: UserResolveService } } ] } ] export const UsersRouting: ModuleWithProviders = RouterModule.forChild(userRoutes) 

UserDetailComponent:

 import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router' import { UsersService } from '../shared/services/users.service'; import { User } from '../shared/models/user'; @Component({ templateUrl: './user-detail.component.html', styleUrls: ['./user-detail.component.scss'] }) export class UserDetailComponent implements OnInit { user: User; constructor(private route: ActivatedRoute) { } ngOnInit() { // OLD CALL without resolve // let id = this.route.snapshot.params['id']; // this.user = this.usersService.getUser(id) // .subscribe((res) => {this.user = res;}, error => {console.log(error)}); // NEW CALL WITH RESOLVE this.route.data.forEach((data: { user: User }) => this.user = data.user ); } } 
+2
angular rxjs angular2-routing angular2-services
source share
1 answer

You can use the catch statement to be able to handle the error without signing yourself:

 @Injectable() export class UserResolveService implements Resolve<User> { user: User; constructor(private service: UsersService) {} resolve(route: ActivatedRouteSnapshot) { let id = route.params['id']; return this.service.getUser(id) .catch(err => { this.router.navigate(['/users']); return Observable.of(false); }); } } 
+4
source

All Articles