SlideShare a Scribd company logo
Angular
Resolver
Tutorial
www.bacancytechnology.com
Angular
Resolver
Tutorial
www.bacancytechnology.com
CONTENTS
What is Angular Resolver?
General Routing Flow v/s Angular Resolver
Routing Flow
Why Choose Angular Resolvers?
Resolve Interface
Angular Resolver Example: How to
Implement?
Output: Angular Resolver Example
Conclusion
We all know how the world of applications is
progressing rapidly. Your application has to
be up to date from user experience to app
performance in such a competitive virtual
world. Users will surely close your
application if it takes time to load.
Developing a real-time app with multiple
server requests/calls can lead to a poor user
experience if it’s not handled properly. You
have to build the app keeping the user
experiences in mind because your
application can’t afford such negative
impacts due to APIs.
Now, you might wonder how to hand
le multiple requests without affecting the
user experience. One of the solutions to this
issue is to implement Angular Resolver.
Today, in this tutorial, we will learn the
implementation of Route Resolvers in
Angular.
What is
Angular
Resolver?
Angular Resolver is used for pre-fetching some
of the data when the user is navigating from
one route to another. It can be defined as a
smooth approach for enhancing user
experience by loading data before the user
navigates to a particular component.
Let’s see what the difference is in the routing
flow if we implement resolvers.
General
Routing Flow
v/s Angular
Resolver
Routing Flow
This section might help you to differentiate
between the routing flow with or without
resolvers.
Steps 2,3 and 4 are done with the help of
resolvers.
So we can conclude that resolver is an
intermediate code that is executed between
clicking the link and loading the component.
Why Choose
Angular
Resolvers?
Angular Resolvers let the application fetch
remote data from the server before the
activatedRoute of the next component is
activated. We don’t require a spinner until the
data is fetched because we won’t be able to
navigate to the next component unless the
server data is retrieved.
To understand it better, let’s take one scenario-
we want to display the array items in a
component received in an unordered list or
table. For that, suppose we have *ngIf=”some
condition” and our business logic depends upon
the length of an array, which will be altered
once the API call is successful.
We might face an issue in such a case as the
component will be ready before receiving the
data (the array item isn’t yet with us).
Here comes Route Resolver to rescue. We can
use Angular’s Route Resolver class for fetching
the data before your component is loaded. And
then, the conditional statements can work
smoothly with the Resolver.
Resolve
Interface
Route- ActivatedRouteSnapshot
State- RouterStateSnapshot
Let’s see how the Resolve Interface looks before
building our demo.
export interface Resolve<T> {
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<T> | Promise<T> | T { return
'Data resolved here...'
}
}
For creating a route resolver, you need to
implement the above interface with your new
class. The interface offers a resolve function
which indeed gets two parameters:
Observable
Promise
Custom type
You can make the API call of which you want to
pre-fetch the data before the component
renders. With the help of route parameters, you
can have route parameters used in the API call.
A resolve method can return:
Keep in mind that only resolved data can be
returned by this method. So, you have to
complete them before sending them to the
route.
I hope the theory so far was helpful for the
starters. Let’s start some coding and develop
our demo application.
Angular
Resolver
Example: How
to
Implement?
Follow the instructions step by step to build the
Angular Resolver example with me.
Create a new Angular application by executing
the below command:
ng new AngularResolver
Create a components folder having three
components – Home, Products, About.
ng g c components/home
ng g c components/about
ng g c components/products
1) Create a new Angular app
2) Create components
Create a service with a file named
product.service.ts to fetch the product’s data
from the remote source. In this service, create a
function called getProducts() that returns an
observable containing data from an API.
// product.service.ts
import { HttpClient } from
'@angular/common/http';
import { Observable } from 'rxjs';
import { Injectable } from '@angular/core';
import { Product } from '../../interfaces/product';
@Injectable({
providedIn: 'root'
})
export class ProductService {
url = 'https://fakestoreapi.com/products?
limit=6';
3) Fetching data
constructor(public http: HttpClient) {}
getProducts(): Observable&lt;Product[]&gt; {
return this.http.get&lt;Product[]&gt;(this.url);
}
}
Create the Product interface having the
following structure.
// product.ts
export interface Product {
id: string;
image: string;
title: string;
price: string;
description: string;
}
4) Product Interface
Create a products-resolver.service.ts file and
implement the resolve method from the
Resolve interface of the router for fetching
server data as follows.
// products-resolver.service.ts
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve }
from '@angular/router';
import { Observable, of } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { ProductService } from
'../product/product.service'
@Injectable({
providedIn: 'root'
})
5) Implement the Resolve method
export class ProductsResolverService
implements Resolve&lt;any&gt; {
constructor(private product: ProductService) {}
resolve(route: ActivatedRouteSnapshot):
Observable&lt;any&gt; {
console.log('Called Get Product in resolver...',
route);
return this.product.getProducts().pipe(
catchError(error =&gt; {
return of('No data');
})
) ;
}
}
The ProductsResolverService class will
automatically subscribe to the getProducts
observable and provide the router with the
fetched data. Only resolved data could be
returned from the method.
Once we are done with the above steps, we need
to configure our routes to specify the data
needed to be prefetched for each component.
For that, modify the routes in the app-
routing.module.ts file.
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from
'@angular/router';
import { AppComponent } from
'./app.component'; import { AboutComponent }
from './components/about/about.component';
import { HomeComponent } from
'./components/home/home.component';
import { ProductsComponent } from
'./components/products/products.component';
6) Route Configuration
import { ProductsResolverService } from
'./services/productsResolver/products-
resolver.service';
const routes: Routes = [
{ path: 'home', component: HomeComponent },
{
path: 'products',
component: ProductsComponent,
resolve: { products: ProductsResolverService}
},
{ path: 'about', component: AboutComponent }
];
@NgModule({ imports:
[RouterModule.forRoot(routes)], exports:
[RouterModule]
})
export class AppRoutingModule {}
Within the routes, we provide a key “resolve”
containing an object to be used for extracting
the data, i.e.,
resolve: { products: ProductsResolverService }
The “resolve” key is assigned with an object
having “products” as a key and
“ProductsResolverService” as its value, as you
can see above. The data is passed to an object
with a property named products.
The resolve() function of
“ProductsResolverService” is invoked, and the
returned Observable is resolved before the
component is loaded. The data extracted from
the API is assigned to the “products” object and
can be accessed in the component.
For accessing the resolved data, we will use the
data property of ActivatedRoute service. In the
products.component.ts file, use the following
code to access the data:
// products.component.ts
import { Component, OnInit } from
'@angular/core';
import { ActivatedRoute } from
'@angular/router';
import { Product } from '../../interfaces/product';
@Component({ selector: 'app-products',
templateUrl: './products.component.html',
styleUrls: ['./products.component.css'] }) export
class ProductsComponent implements OnInit {
products: Product[];
constructor(private activatedRoute:
ActivatedRoute) {}
7) Access the Resolved Data
ngOnInit(): void {
console.log(
'Activated route data in Component:::',
this.activatedRoute.data );
this.activatedRoute.data.subscribe((response:
any) =&gt; {
console.log('PRODUCT FETCHING', response);
this.products = response.products;
console.log('PRODUCT FETCHED');
});
}
}
To display the data, use the following code in
the products.component.html file.
// products.component.html
8) Display the data
<div class="wrapper">
<div *ngFor="let product of products"
class="card">
<img [src]="product.image"/>
<div>
<h3>{{product.title}}<;/h3>
<p class="price">Price = ${{product.price}}</p>
<p>{{product.description}}</p>
</div>
<div class="cart-btn-div">
<button type ="button">Add to Cart</button>
</div>
</div>
</div>
For a better experience, integrate the loading
spinner, add the following code in the
app.component.ts and app.component.html
files.
9) Add a Loading Spinner
// app.component.html
<style>
.content {
display: flex;
margin: 82px auto 32px;
flex-direction: column;
align-items: center;
}
.card-container {
display: flex;
flex-wrap: wrap;
justify-content: center;
margin-top: 16px;
}
.card {
border: 1px solid #eee;
background-color: #fafafa;
height: 40px;
width: 200px;
margin: 0 8px 16px;
padding: 16px;
display: flex;
justify-content: center;
align-items: center;
}
a,
a:visited,
a:hover {
color: #1976d2;
text-decoration: none;
}
a:hover {
color: #125699;
}
}
</style>
<div *ngIf="loading" id="myModal"
class="modal">
<div class="lds-roller">
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
<div class="content" role="main">
<div class="card-container">
<a class="card" routerLink="/home"> &lt;
<span>Home</span>
</a>
<a class="card" routerLink="/products">
<span>Products</span>
</a>
<a class="card" routerLink="/about">
<span>About</span>
</a>
</div>
</div>
<router-outlet></router-outlet>
// app.component.ts
import { Component } from '@angular/core';
import {
NavigationCancel,
NavigationEnd,
NavigationError,
NavigationStart,
Router
} from '@angular/router';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
loading = false;
title = 'angu-res';
constructor(public router: Router) {
this.router.events.subscribe(ev =&gt; {
if (ev instanceof NavigationStart) {
this.loading = true;
}
if (
ev instanceof NavigationEnd ||
ev instanceof NavigationCancel ||
ev instanceof NavigationError
) {
this.loading = false;
}
});
}
}
You can get more such spinner templates from
loading.io.
The entire source code of the Angular Resolver
example is available on the Github repository.
Output:
Angular
Resolver
Example
Here’s a video of the output of the Angular
Resolver Example.
Watch Video
Conclusion
So, this was about implementing Route
Resolver in Angular. I hope the purpose of the
blog is served the way you’ve expected. Feel
free to visit Angular Tutorials to explore and
learning Angular.
At Bacancy, we have skilled and experienced
Angular developers having fundamental and
advanced knowledge. If you are looking for
dedicated and enthusiastic developers, contact
us to hire Angular developer. We assure to fulfill
your project requirements with our expertise.
Thank You
www.bacancytechnology.com

More Related Content

Angular resolver tutorial

  • 2. CONTENTS What is Angular Resolver? General Routing Flow v/s Angular Resolver Routing Flow Why Choose Angular Resolvers? Resolve Interface Angular Resolver Example: How to Implement? Output: Angular Resolver Example Conclusion
  • 3. We all know how the world of applications is progressing rapidly. Your application has to be up to date from user experience to app performance in such a competitive virtual world. Users will surely close your application if it takes time to load. Developing a real-time app with multiple server requests/calls can lead to a poor user experience if it’s not handled properly. You have to build the app keeping the user experiences in mind because your application can’t afford such negative impacts due to APIs. Now, you might wonder how to hand le multiple requests without affecting the user experience. One of the solutions to this issue is to implement Angular Resolver. Today, in this tutorial, we will learn the implementation of Route Resolvers in Angular.
  • 5. Angular Resolver is used for pre-fetching some of the data when the user is navigating from one route to another. It can be defined as a smooth approach for enhancing user experience by loading data before the user navigates to a particular component. Let’s see what the difference is in the routing flow if we implement resolvers.
  • 7. This section might help you to differentiate between the routing flow with or without resolvers. Steps 2,3 and 4 are done with the help of resolvers. So we can conclude that resolver is an intermediate code that is executed between clicking the link and loading the component.
  • 9. Angular Resolvers let the application fetch remote data from the server before the activatedRoute of the next component is activated. We don’t require a spinner until the data is fetched because we won’t be able to navigate to the next component unless the server data is retrieved. To understand it better, let’s take one scenario- we want to display the array items in a component received in an unordered list or table. For that, suppose we have *ngIf=”some condition” and our business logic depends upon the length of an array, which will be altered once the API call is successful. We might face an issue in such a case as the component will be ready before receiving the data (the array item isn’t yet with us).
  • 10. Here comes Route Resolver to rescue. We can use Angular’s Route Resolver class for fetching the data before your component is loaded. And then, the conditional statements can work smoothly with the Resolver.
  • 12. Route- ActivatedRouteSnapshot State- RouterStateSnapshot Let’s see how the Resolve Interface looks before building our demo. export interface Resolve<T> { resolve( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable<T> | Promise<T> | T { return 'Data resolved here...' } } For creating a route resolver, you need to implement the above interface with your new class. The interface offers a resolve function which indeed gets two parameters:
  • 13. Observable Promise Custom type You can make the API call of which you want to pre-fetch the data before the component renders. With the help of route parameters, you can have route parameters used in the API call. A resolve method can return: Keep in mind that only resolved data can be returned by this method. So, you have to complete them before sending them to the route. I hope the theory so far was helpful for the starters. Let’s start some coding and develop our demo application.
  • 15. Follow the instructions step by step to build the Angular Resolver example with me. Create a new Angular application by executing the below command: ng new AngularResolver Create a components folder having three components – Home, Products, About. ng g c components/home ng g c components/about ng g c components/products 1) Create a new Angular app 2) Create components
  • 16. Create a service with a file named product.service.ts to fetch the product’s data from the remote source. In this service, create a function called getProducts() that returns an observable containing data from an API. // product.service.ts import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { Injectable } from '@angular/core'; import { Product } from '../../interfaces/product'; @Injectable({ providedIn: 'root' }) export class ProductService { url = 'https://fakestoreapi.com/products? limit=6'; 3) Fetching data
  • 17. constructor(public http: HttpClient) {} getProducts(): Observable&lt;Product[]&gt; { return this.http.get&lt;Product[]&gt;(this.url); } } Create the Product interface having the following structure. // product.ts export interface Product { id: string; image: string; title: string; price: string; description: string; } 4) Product Interface
  • 18. Create a products-resolver.service.ts file and implement the resolve method from the Resolve interface of the router for fetching server data as follows. // products-resolver.service.ts import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, Resolve } from '@angular/router'; import { Observable, of } from 'rxjs'; import { catchError } from 'rxjs/operators'; import { ProductService } from '../product/product.service' @Injectable({ providedIn: 'root' }) 5) Implement the Resolve method
  • 19. export class ProductsResolverService implements Resolve&lt;any&gt; { constructor(private product: ProductService) {} resolve(route: ActivatedRouteSnapshot): Observable&lt;any&gt; { console.log('Called Get Product in resolver...', route); return this.product.getProducts().pipe( catchError(error =&gt; { return of('No data'); }) ) ; } } The ProductsResolverService class will automatically subscribe to the getProducts observable and provide the router with the fetched data. Only resolved data could be returned from the method.
  • 20. Once we are done with the above steps, we need to configure our routes to specify the data needed to be prefetched for each component. For that, modify the routes in the app- routing.module.ts file. // app-routing.module.ts import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; import { AppComponent } from './app.component'; import { AboutComponent } from './components/about/about.component'; import { HomeComponent } from './components/home/home.component'; import { ProductsComponent } from './components/products/products.component'; 6) Route Configuration
  • 21. import { ProductsResolverService } from './services/productsResolver/products- resolver.service'; const routes: Routes = [ { path: 'home', component: HomeComponent }, { path: 'products', component: ProductsComponent, resolve: { products: ProductsResolverService} }, { path: 'about', component: AboutComponent } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule {}
  • 22. Within the routes, we provide a key “resolve” containing an object to be used for extracting the data, i.e., resolve: { products: ProductsResolverService } The “resolve” key is assigned with an object having “products” as a key and “ProductsResolverService” as its value, as you can see above. The data is passed to an object with a property named products. The resolve() function of “ProductsResolverService” is invoked, and the returned Observable is resolved before the component is loaded. The data extracted from the API is assigned to the “products” object and can be accessed in the component.
  • 23. For accessing the resolved data, we will use the data property of ActivatedRoute service. In the products.component.ts file, use the following code to access the data: // products.component.ts import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Product } from '../../interfaces/product'; @Component({ selector: 'app-products', templateUrl: './products.component.html', styleUrls: ['./products.component.css'] }) export class ProductsComponent implements OnInit { products: Product[]; constructor(private activatedRoute: ActivatedRoute) {} 7) Access the Resolved Data
  • 24. ngOnInit(): void { console.log( 'Activated route data in Component:::', this.activatedRoute.data ); this.activatedRoute.data.subscribe((response: any) =&gt; { console.log('PRODUCT FETCHING', response); this.products = response.products; console.log('PRODUCT FETCHED'); }); } } To display the data, use the following code in the products.component.html file. // products.component.html 8) Display the data
  • 25. <div class="wrapper"> <div *ngFor="let product of products" class="card"> <img [src]="product.image"/> <div> <h3>{{product.title}}<;/h3> <p class="price">Price = ${{product.price}}</p> <p>{{product.description}}</p> </div> <div class="cart-btn-div"> <button type ="button">Add to Cart</button> </div> </div> </div> For a better experience, integrate the loading spinner, add the following code in the app.component.ts and app.component.html files. 9) Add a Loading Spinner
  • 26. // app.component.html <style> .content { display: flex; margin: 82px auto 32px; flex-direction: column; align-items: center; } .card-container { display: flex; flex-wrap: wrap; justify-content: center; margin-top: 16px; } .card { border: 1px solid #eee; background-color: #fafafa; height: 40px; width: 200px; margin: 0 8px 16px; padding: 16px;
  • 27. display: flex; justify-content: center; align-items: center; } a, a:visited, a:hover { color: #1976d2; text-decoration: none; } a:hover { color: #125699; } } </style> <div *ngIf="loading" id="myModal" class="modal"> <div class="lds-roller"> <div></div> <div></div> <div></div> <div></div>
  • 28. <div></div> <div></div> <div></div> <div></div> </div> </div> <div class="content" role="main"> <div class="card-container"> <a class="card" routerLink="/home"> &lt; <span>Home</span> </a> <a class="card" routerLink="/products"> <span>Products</span> </a> <a class="card" routerLink="/about"> <span>About</span> </a> </div> </div> <router-outlet></router-outlet>
  • 29. // app.component.ts import { Component } from '@angular/core'; import { NavigationCancel, NavigationEnd, NavigationError, NavigationStart, Router } from '@angular/router'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { loading = false; title = 'angu-res'; constructor(public router: Router) { this.router.events.subscribe(ev =&gt; { if (ev instanceof NavigationStart) {
  • 30. this.loading = true; } if ( ev instanceof NavigationEnd || ev instanceof NavigationCancel || ev instanceof NavigationError ) { this.loading = false; } }); } } You can get more such spinner templates from loading.io. The entire source code of the Angular Resolver example is available on the Github repository.
  • 32. Here’s a video of the output of the Angular Resolver Example. Watch Video
  • 34. So, this was about implementing Route Resolver in Angular. I hope the purpose of the blog is served the way you’ve expected. Feel free to visit Angular Tutorials to explore and learning Angular. At Bacancy, we have skilled and experienced Angular developers having fundamental and advanced knowledge. If you are looking for dedicated and enthusiastic developers, contact us to hire Angular developer. We assure to fulfill your project requirements with our expertise.