Quick Summary
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 handle 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.
Are you tired of watching your Angular app struggle to load data, leaving users impatiently tapping their fingers? We’ve all been there—waiting for screens to settle, feeling frustrated by sluggish performance. However, there’s a robust solution to this challenge- Angular Resolver
In this blog tutorial, we’ll explore Angular resolvers and learn how they can optimize data fetching in Angular applications with extensive examples. To understand it better, we will also cover the difference between general routing and resolvers in Angular routing flow.
Angular Resolver is used to pre-fetch data when the user navigates from one route to another. It can be defined as a smooth approach to enhancing user experience by loading data before the user navigates to a particular component.
Let’s understand the reasons for choosing resolver in Angular and what benefits it can provide to your application.
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 of 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.
Struggling to build high-performance Angular applications?
Here we are to lessen your hustles! Contact one of the best Angular Development Company who will help you meet your project requirements efficiently with commendable problem-solving skills.
In this case, we might face an issue as the component will be ready before receiving the data (the array item isn’t yet with us).
Here comes Route Resolver to the rescue. We can use Angular’s Route Resolve class to fetch the data before your component is loaded. Then, the conditional statements can work smoothly with the Resolver.
This section might help you to differentiate between the routing flow with or without resolvers.
You must note that steps 2, 3, and 4 are done with the help of resolvers. So, we can conclude that the resolver Angular is an intermediate code executed between clicking the link and loading the component.
Let’s see how the Resolve Interface looks before building our demo.
export interface Resolve { resolve( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable | Promise | 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:
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.
Follow the instructions step by step to build the Angular Resolver example with me.
Create a new Angular application by executing the below command:
Create a components folder having three components – Home, Products, About.
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'; constructor(public http: HttpClient) {} getProducts(): Observable { return this.http.get (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; }
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' }) export class ProductsResolverService implements Resolve { constructor(private product: ProductService) {} resolve(route: ActivatedRouteSnapshot): Observable { 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.
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'; 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.,
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) {} 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
For a better experience, integrate the loading spinner, add the following code in the app.component.ts and app.component.html files.
// app.component.html
// 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) { this.loading = true; } if ( ev instanceof NavigationEnd || ev instanceof NavigationCancel || ev instanceof NavigationError ) { this.loading = false; } }); } }
However, if you are still struggling with resolver, you can partner with Angular consulting services providers for insightful advice and strategic guidance.
You can get more such spinner templates from loading.io. Moreover, the entire source code of the Resolver Angular example is available on the Github repository.
So, this was about implementing Route Resolver in Angular. It is a robust mechanism that enhances user experience by fetching essential data before the user navigates to a particular component. You can even visit Angular Tutorials to explore and learning Angular.
At Bacancy, we have skilled and experienced Angular developers with fundamental and advanced knowledge. If you are looking for dedicated and enthusiastic developers, contact us to hire Angularjs developer for fulfilling your project requirements with the expertise.
Your Success Is Guaranteed !
We accelerate the release of digital product and guaranteed their success
We Use Slack, Jira & GitHub for Accurate Deployment and Effective Communication.