Tuesday 4 July 2023

what is Route Guards in Angular

In Angular, implementing proper access control to routes is essential for building secure and user-friendly applications. Fortunately, Angular offers a range of guards that enable developers to control and protect routes based on specific conditions. Whether it involves restricting access to certain routes, limiting access to specific users, prompting users before leaving a route, or prefetching data before activating a route, Angular's route guards provide the necessary functionality. In this article, we will explore the different types of guards available in Angular and learn how to effectively implement them with practical examples.

Latest Angular Router Guards

Below is the order in which Guard are processed in the following order:
  • canDeactivate
  • canLoad
  • canActivateChild
  • canActivate
  • resolve
Building a Guard Service : 

To implement a route guard in Angular, you need to create a guard service that implements a specific guard type provided by Angular. This service will contain a method associated with the guard type. Let's take a look at how to build a guard service:

typescript
import { Injectable } from '@angular/core'; import { CanActivate, Router } from '@angular/router'; @Injectable({ providedIn: 'root' }) export class AuthGardService implements CanActivate { canActivate(): boolean { // Implement your authentication logic here // For example, check if the user is logged in and has the necessary roles/permissions // If the user is authenticated, return true to allow access to the route // If the user is not authenticated, you can redirect them to the login page or any other route using the Router service and return false // For demonstration purposes, let's assume the user is already authenticated and has access return true; } }

Once you have created the guard service, you can utilize it on the route in the following manner:

typescript
import { AuthGuard } from './auth-guard.service.ts'; // ... { path: ':id', component: CoderevisitedDetailComponent, resolve: { article: CoderevisitedResolver }, canActivate: [AuthGuard] }
We imported the AuthGuard from './auth-guard.service.ts'. Then, we define a route configuration object where we specify the path :id, the CoderevisitedComponent as the component to render for that route, and the CoderevisitedResolver for resolving data before activating the route. Additionally, we include the canActivate property with the value [AuthGuard] to indicate that the AuthGuard should be used to guard access to this route.

Angular Guard Types

1.canActivate (Guard navigation to a route):

The canActivate guard is triggered when the URL changes to a route that matches the guard. It is commonly used to 
  • limit route access to specific users 
  • ensure that certain prerequisites are met
You can generate this guard using the Angular CLI, and it can be implemented as follows:

bash
ng generate guard thecoderevisited/auth
// shorthand - ng g g thecoderevisited/auth

When you run this command in the terminal, Angular CLI will prompt you to choose the guard type you want to implement, excluding canDeactivate and canLoad guards. After selecting the desired guard type, the CLI will generate the guard file along with its associated testing file.

It's important to note that the generated files will follow the Angular guard template, and you can customize them according to your specific needs.

2. canActivateChild (Guard navigation to a child route):

Similar to canActivate, the canActivateChild guard is used when activating a child route instead of the route itself. It checks criteria before activating a child route, such as 
  • limiting access
  • ensuring prerequisites are met

3. canDeactivate (Guard navigation away from a route):

The canDeactivate guard is responsible for checking criteria before leaving a route. It is commonly used to handle scenarios such as 
  • checking for unsaved changes
  • confirming incomplete operations
  • alerting the user
Unlike other guard types, canDeactivate requires a generic parameter to identify the component using the guard. Here's an example of how to use it:

typescript
import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, RouterStateSnapshot, CanDeactivate, Router } from '@angular/router'; import { Observable } from 'rxjs'; import { EditArticleComponent } from './coderevisited.component.ts'; @Injectable({ providedIn: 'root' }) export class CoderevisitedGuard implements CanDeactivate<EditArticleComponent> { canDeactivate( component: CoderevisitedComponent, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot, nextState?: RouterStateSnapshot ): boolean | Observable<boolean> | Promise<boolean> { // Implement your canDeactivate logic here // For example, check if the user has unsaved changes and prompt for confirmation before leaving the route // You can access the component, current route, current state, and next state within this method // For demonstration purposes, let's assume there are no unsaved changes and allow deactivation return true; } }

We imported the CoderevisitedComponent from './coderevisited.component.ts'.

Then, we create the 
CoderevisitedGuard class that implements the CanDeactivate interface with the CoderevisitedComponent type. The canDeactivate method is implemented to handle the deactivation logic. You can customize this method to check for unsaved changes, prompt for confirmation, or perform any other necessary checks before allowing the deactivation of the component.

Please ensure that you have the correct import path for the CoderevisitedComponent and adjust it accordingly based on its actual location in your project.

The last step is, now add this guard to the route in the module:

typescript
import { CoderevisitedGuard } from './coderevisited.guard.service.ts'; import { CoderevisitedComponent } from './coderevisited.component.ts'; // ... { path: ':id/edit', component: CoderevisitedComponent, canDeactivate: [CoderevisitedGuard], resolve: { article: CoderevisitedResolver } }

4. canLoad (Prevent asynchronous routing):

The canLoad guard prevents the application from loading an entire module or component lazily (lazy loading) if the user is not authorized. It differs from canActivate as it optimizes the app's performance by preventing the loading of unauthorized modules/components. 

Here's an example of its implementation:

typescript
class UserToken {} class Permissions { canLoadChildren(user: UserToken, id: string, segments: UrlSegment[]): boolean { return true; } } @Injectable() class CanLoadCoderevisitedArticles implements CanLoad { constructor(private permissions: Permissions, private currentUser: UserToken) {} canLoad(route: Route, segments: UrlSegment[]): Observable<boolean> | Promise<boolean> | boolean { return this.permissions.canLoadChildren(this.currentUser, route.path, segments); } }

Now add this guard to the route in the module:

typescript
@NgModule({ imports: [ RouterModule.forRoot([ { path: 'coderevisited-team-artiles/:id', component: CoderevisitedTeamArticlesComponent, canLoad: [CanLoadCoderevisitedArticles] } ]) ], providers: [CanLoadCoderevisitedArticles, UserToken, Permissions] }) class AppModule {}

5. resolve (Prefetch data before activating a route):

The resolve guard allows you to fetch data before navigating to a route. It ensures that the component is rendered along with the data, avoiding empty components or the need for spinners. 

Example : 

typescript
@Injectable({ providedIn: 'root' }) export class CoderevisitedResolver implements Resolve<CoderevisitedComponent> { constructor(private articlesService: ArticlesService) {} resolve( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable<any> | Promise<any> | any { return this.articlesService.getArticles(route.paramMap.get('id')); } }

Now add this guard to the route in the module:

typescript
@NgModule({ imports: [ RouterModule.forRoot([ { path: 'articles/:id', component: CoderevisitedComponent, resolve: { articles: CoderevisitedResolver } } ]) ], exports: [RouterModule] }) export class AppRoutingModule {}

In the code above, we have the AppRoutingModule class decorated with @NgModule. Within the imports array, we configure the router module using RouterModule.forRoot(). Inside the router configuration, we define a route for the path 'articles/:id'. The CoderevisitedComponent is set as the component to render for this route. We include a resolve property that maps the 'articles' key to the CoderevisitedResolver class. This means that before activating the route, the CoderevisitedResolver will be used to resolve the 'articles' data.

Please make sure to provide the correct import paths for RouterModule, CoderevisitedComponent, and CoderevisitedResolver based on their actual file locations in your project.

In conclusion, Angular Router Guards play a vital role in ensuring the security and access control of your Angular applications. By implementing these guards, you can effectively manage route navigation, protect sensitive areas, and perform necessary checks before activating routes.

Throughout this article, we have explored the different types of Angular Router Guards and provided practical examples to demonstrate their usage. By understanding and applying these guards in your projects, you can create secure and user-friendly Angular applications.

By incorporating Angular Router Guards into your development process, you can elevate your web development skills to new heights. These guards serve as valuable tools for enhancing the security and reliability of your Angular applications. So, don't hesitate to start utilizing and implementing Angular Router Guards today to unlock the full potential of your web development endeavors.

Read more :

No comments:

Post a Comment

Seven front-end development trends in 2023-2024

With the increasing prevalence of apps in the digital landscape , the role of front-end developers remains essential. While apps aim to ove...

Popular Posts