This document discusses Angular resolvers, which are used to pre-fetch data before navigating to a component. Angular resolvers implement the Resolve interface to return data via Observable or Promise before the route is activated. An example is provided demonstrating how to create a resolver service to fetch product data from an API, configure routes to use the resolver, and access the resolved data in a component. A loading spinner is also added to improve the user experience while data is loading.
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<Product[]> {
return this.http.get<Product[]>(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<any> {
constructor(private product: ProductService) {}
resolve(route: ActivatedRouteSnapshot):
Observable<any> {
console.log('Called Get Product in resolver...',
route);
return this.product.getProducts().pipe(
catchError(error => {
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
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) => {
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
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 => {
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.
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.