Understand Angular 8 Route Resolvers

By Digamber Rawat Last updated on
Today we are going to understand Route resolvers in Angular 7, route resolver gets the data before the component is ready.

Why we use route resolver in Angular?

Think about the scenario when you are using *ngIf="some condition" and your logic is depending upon the length of the array.

In this situation you might get into the problem, because your data will come up after the component is ready. Here route resolver come in handy, Angular’s Route resolver class will fetch your data before the component is ready. Your conditional statements will work smoothly with route resolver class.

Route Resolver Class in Angular

Here is the route resolver class, it can be used with Observable and Promise as well

export interface Resolve<T> {
   resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<T> | Promise<T> | T { 
      return 'Data resolved here...'
   }
}

Simple Route Resolver in Angular 7

We are going to explore a simple route resolver in this tutorial. The data will be fetched from JSON Placeholder’s Users API. Routing happens right after fetching the data. We are going to design a simple resolver first.

We will create a fresh file to create a separate class meant for the resolver.

import { Injectable } from '@angular/core';
import { UsersListService } from './../service/users-list.service';
import { Resolve } from '@angular/router';

@Injectable()
export class RouteResolver implements Resolve<any> {

   constructor(public usersListService: UsersListService) { }

   resolve() {
      return this.usersListService.getUsers()
   }
   
}

The class we have created has an Angular resolve method, which is capable of implementing the Resolve interface of the router. Only resolved data will be returned from that method.

Here, in this case, we are returning an observable.

The configuration of the route

Now it is time for us to make sure that the routing module has our resolver.

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

// Components
import { HomeComponent } from './components/home/home.component';
import { UsersComponent } from './components/users/users.component';

// Route resolver array
import { RouteResolver } from './resolvers/route.resolver';

const routes: Routes = [
  { 
    path: 'home', 
    pathMatch: 'full',
    component: HomeComponent
  },
  {
    path: 'users',
    component: UsersComponent,
    resolve: {
      routeResolver: RouteResolver
    },
  }, 
  {
    path: '**',
    redirectTo: '/',
    pathMatch: 'full'
  },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
  providers: [RouteResolver] // Don't forget to pass RouteResolver into the providers array
})

export class AppRoutingModule { }

Notice how our resolver is provided just like a service and then we include the resolver with our route definition. Here the resolved data will be available under the message key.

Accessing Resolved Data in the Component

In order to access the resolved data we can also use the data property of ActivatedRoute service:

import { Component, OnInit } from '@angular/core';
import { UsersListService } from './../../service/users-list.service';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-users',
  templateUrl: './users.component.html',
  styleUrls: ['./users.component.css']
})

export class UsersComponent implements OnInit {

  Users: any = [];

  constructor(
    private usersListService: UsersListService,
    private actRoute: ActivatedRoute
  ) { }

  ngOnInit() {
    // Can access route resolver data with ActivatedRoute route service
    this.actRoute.data.subscribe(data => {
      console.log('Check route resolver data')
      console.log(data)
    })

    // Some other method :)
    this.usersListService.getUsers().subscribe((data: {}) => {
      this.Users = data;
    })
  }

}

Displaying resolved data in Angular HTML template.

<ul class="list">
  <li *ngFor="let users of Users">{{users.name}}</li>
</ul>

How to resolve data from an API?

Let’s take a look at a real-life example next. We are going to get some data from a specific API. We have chosen JSON placeholder’s API as a data source.

Let’s take a look at our service below. We have made use of the new HttpClient as well:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})

export class UsersListService {

  url = 'https://jsonplaceholder.typicode.com/users';

  constructor(public http: HttpClient) { }

  getUsers() {
     return this.http.get(this.url);
  }

}

Route Resolver Handling errors in Angular 7

In order to deal with the error while getting the data, you may use RxJ’s catchError operator by catching the error in the resolver.

Let’s take a look at an example below:

import { Injectable } from '@angular/core';
import { UsersListService } from './../service/users-list.service';
import { Resolve } from '@angular/router';

import { Observable, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';


@Injectable()
export class RouteResolver implements Resolve<any> {
   constructor(public usersListService: UsersListService) { }

   resolve() {
      return this.usersListService.getUsers().pipe(
         catchError((error) => {
            return of('No data');
         })
      )
   }
}

You could also return an empty observable in case of an error. Here in this case the user will not be dispatched to the new route.

import { empty } from 'rxjs';
resolve() {
   return this.usersListService.getUsers().pipe(
      catchError((error) => {
         return empty();
      })
   )
}

Download Angular Route Resolver Project Files

GitHub Resources

Digamber Rawat
Digamber Rawat

Full stack developer with a passion for UI/UX design. I create beautiful and useful digital products to solve people’s problem and make their life easy.