Angular Routing: A Step-by-Step Guide

Angular Routing: A Step-By-Step Guide

This tutorial will guide you through the process of setting up and using Angular Routing in your Angular development projects. Angular Routing is a powerful feature that allows you to create single-page applications with multiple views, enabling users to navigate between different pages without a full page refresh. This tutorial will cover the basics of Angular Routing, including installing the Angular Router, configuring routes, creating components for routes, navigating between routes, using route guards, and implementing child routes. By the end of this tutorial, you will have a solid understanding of Angular Routing and be able to implement it in your own projects.

angular routing step step guide

What is Angular Routing?

Angular Routing is a mechanism that allows you to define routes in your Angular application and map them to different components. It enables you to create a single-page application with multiple views, where each view corresponds to a different URL. When a user navigates to a specific URL, Angular Routing will load the corresponding component and display it on the page without a full page refresh.

Why is Angular Routing important?

Angular Routing is important because it provides a seamless user experience by allowing users to navigate between different views without the need for a full page refresh. This improves performance and makes your application feel more like a traditional desktop application. Additionally, Angular Routing enables you to create deep links that can be bookmarked and shared, making it easier for users to navigate directly to specific sections of your application.

Setting up Angular Routing

To get started with Angular Routing, you need to install the Angular Router and configure your routes.

Installing Angular Router

First, you need to install the Angular Router package. Open a terminal window and navigate to your project directory. Run the following command to install the Angular Router:

npm install @angular/router

Importing Router Module

Next, you need to import the Router module in your Angular application. Open the app.module.ts file and add the following line at the top of the file:

import { RouterModule } from '@angular/router';

Configuring Routes

After importing the Router module, you need to configure your routes. In your app.module.ts file, add the following code inside the @NgModule decorator:

@NgModule({
  imports: [
    RouterModule.forRoot([
      // Add your routes here
    ])
  ],
  exports: [RouterModule]
})
export class AppModule { }

The RouterModule.forRoot() method is used to configure the routes for your application. Inside the method, you can define your routes as an array of objects. Each route object should have a path property, which specifies the URL path for the route, and a component property, which specifies the component that should be loaded when the route is navigated to.

Defining Routes

Now that you have configured the routes, you can define them in your application. Open the app.module.ts file and add the following code inside the RouterModule.forRoot() method:

RouterModule.forRoot([
  { path: '', component: HomeComponent },
  { path: 'about', component: AboutComponent },
  { path: 'contact', component: ContactComponent }
])

In this example, we have defined three routes: the root route, which maps to the HomeComponent, the /about route, which maps to the AboutComponent, and the /contact route, which maps to the ContactComponent. When a user navigates to these URLs, the corresponding components will be loaded and displayed on the page.

Creating Components for Routes

Now that you have defined your routes, it's time to create the components that will be loaded when the routes are navigated to.

Configuring Route Paths

To configure the route paths for your components, open the app-routing.module.ts file and add the following code:

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'about', component: AboutComponent },
  { path: 'contact', component: ContactComponent }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

In this code, we import the RouterModule from @angular/router and define an array of routes. Each route object in the array has a path property and a component property, just like we did in the previous section. We then use the RouterModule.forChild() method to configure the routes for the current module, and export the RouterModule so that it can be used in other modules.

Adding Route Parameters

Sometimes, you may need to pass parameters to your routes. To add route parameters, you can use the :param syntax in the path property of your route object. For example, if you have a route that needs to receive an id parameter, you can define it like this:

{ path: 'user/:id', component: UserComponent }

In this example, the :id parameter is a placeholder that can be filled with a specific value when the route is navigated to. In your component, you can access the value of the parameter using the ActivatedRoute service.

Now that you have defined your routes and created the components, you can navigate between routes in your application.

To navigate between routes, you can use the RouterLink directive. The RouterLink directive is used to create links that navigate to specific routes in your application. To use the RouterLink directive, add the following code to your HTML template:

<a routerLink="/">Home</a>
<a routerLink="/about">About</a>
<a routerLink="/contact">Contact</a>

In this example, we have created three links that navigate to the root route, the /about route, and the /contact route, respectively. When a user clicks on one of these links, the corresponding route will be navigated to.

Programmatic Navigation

In addition to using the RouterLink directive, you can also navigate to routes programmatically using the Router service. To use the Router service, import it into your component and inject it into the constructor, like this:

import { Router } from '@angular/router';

constructor(private router: Router) { }

Once you have injected the Router service, you can use its navigate() method to navigate to a specific route. For example, to navigate to the /about route programmatically, you can use the following code:

this.router.navigate(['/about']);

In this example, we use the navigate() method to navigate to the /about route. The argument passed to the method is an array containing the route path.

Route Guards

Route guards are used to control access to routes in your application. They allow you to prevent unauthorized users from accessing certain routes, or prompt the user to confirm navigation away from a route.

CanActivate

The CanActivate interface is a route guard that allows you to control access to a route based on certain conditions. To use the CanActivate interface, you need to create a service that implements the interface and provide it to the canActivate property of your route object. For example, to create a AuthGuard service that prevents unauthorized users from accessing a route, you can use the following code:

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    // Add your authentication logic here
  }
}

In this example, we have created an AuthGuard service that implements the CanActivate interface. The canActivate() method is called when the route is navigated to and should return a boolean value indicating whether the user is authorized to access the route. You can add your own authentication logic inside the canActivate() method.

To use the AuthGuard service, you need to provide it to the canActivate property of your route object, like this:

{ path: 'admin', component: AdminComponent, canActivate: [AuthGuard] }

In this example, the AuthGuard service is provided to the canActivate property of the /admin route. This means that only authorized users will be able to access the /admin route.

CanDeactivate

The CanDeactivate interface is a route guard that allows you to prompt the user to confirm navigation away from a route. To use the CanDeactivate interface, you need to create a component that implements the interface and provide it to the canDeactivate property of your route object. For example, to create a FormComponent that prompts the user to confirm navigation away from a form, you can use the following code:

export interface CanComponentDeactivate {
  canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}

export class FormComponent implements CanComponentDeactivate {
  canDeactivate(): Observable<boolean> | Promise<boolean> | boolean {
    // Add your confirmation logic here
  }
}

In this example, we have created a FormComponent that implements the CanComponentDeactivate interface. The canDeactivate() method is called when the user tries to navigate away from the route and should return a boolean value indicating whether the user should be prompted to confirm navigation. You can add your own confirmation logic inside the canDeactivate() method.

To use the FormComponent, you need to provide it to the canDeactivate property of your route object, like this:

{ path: 'form', component: FormComponent, canDeactivate: [FormGuard] }

In this example, the FormComponent is provided to the canDeactivate property of the /form route. This means that when the user tries to navigate away from the /form route, they will be prompted to confirm navigation.

Resolve

The Resolve interface is a route guard that allows you to fetch data before the route is activated. To use the Resolve interface, you need to create a service that implements the interface and provide it to the resolve property of your route object. For example, to create a DataResolver service that fetches data before activating a route, you can use the following code:

@Injectable({
  providedIn: 'root'
})
export class DataResolver implements Resolve<any> {
  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<any> | Promise<any> | any {
    // Add your data fetching logic here
  }
}

In this example, we have created a DataResolver service that implements the Resolve interface. The resolve() method is called before the route is activated and should return the data that you want to fetch. You can add your own data fetching logic inside the resolve() method.

To use the DataResolver service, you need to provide it to the resolve property of your route object, like this:

{ path: 'data', component: DataComponent, resolve: { data: DataResolver } }

In this example, the DataResolver service is provided to the resolve property of the /data route. This means that the data will be fetched before the /data route is activated, and the fetched data will be available in the DataComponent.

Child Routes

Child routes are used to create nested routes in your application. They allow you to define routes that are children of another route, enabling you to create more complex routing structures.

Nested Routes

To define nested routes, you need to create a component that acts as the parent component for the child routes. In this parent component, you need to define a <router-outlet> element, which is used to render the child routes. For example, to create a ParentComponent with two child routes, you can use the following code:

const routes: Routes = [
  {
    path: 'parent',
    component: ParentComponent,
    children: [
      { path: '', redirectTo: 'child1', pathMatch: 'full' },
      { path: 'child1', component: Child1Component },
      { path: 'child2', component: Child2Component }
    ]
  }
];

In this example, we have defined a ParentComponent with two child routes: /parent/child1 and /parent/child2. The redirectTo property is used to redirect the user to the child1 route when they navigate to the /parent route.

To render the child routes, add the <router-outlet> element to the template of the ParentComponent, like this:

<router-outlet></router-outlet>

When the user navigates to the /parent route, the ParentComponent will be loaded and the <router-outlet> element will render the child routes.

Lazy Loading

Lazy loading is a technique that allows you to load modules and their routes on-demand, instead of loading them all at once. This can significantly improve the performance of your application, especially if you have a large number of routes.

To implement lazy loading, you need to create a separate module for the routes that you want to lazy load. In this module, you need to define your routes as children of the module's own routes. For example, to create a LazyModule with a lazy loaded route, you can use the following code:

const routes: Routes = [
  {
    path: 'lazy',
    loadChildren: () => import('./lazy.module').then(m => m.LazyModule)
  }
];

In this example, we have defined a LazyModule with a lazy loaded route: /lazy. The loadChildren property is used to specify the path to the module file that should be loaded when the route is navigated to. The import() function is used to dynamically import the module file, and the then() method is used to extract the module from the imported file.

To enable lazy loading, you need to update your app-routing.module.ts file to use the loadChildren property instead of the component property for the lazy loaded route. For example, you can use the following code:

const routes: Routes = [
  { path: 'lazy', loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule) }
];

In this example, the /lazy route is lazy loaded from the ./lazy/lazy.module file.

Conclusion

In this tutorial, we have covered the basics of Angular Routing, including installing the Angular Router, configuring routes, creating components for routes, navigating between routes, using route guards, and implementing child routes. By following this step-by-step guide, you should now have a solid understanding of Angular Routing and be able to implement it in your own Angular development projects. Angular Routing is a powerful feature that can greatly enhance the user experience of your applications, so make sure to take advantage of it in your future projects. Happy coding!