DEV Community

Gaëtan Redin
Gaëtan Redin

Posted on • Originally published at Medium on

Basic Routing in Angular

Angular for Everyone: Part 11

How to use routing in Angular?

Why use Routing?

Hey, I know you are here because you have developed an extensive application, and you have forgotten to implements routing, or maybe you already know the basics, and you are just there to get some tips about it. In both cases, I’m going to try to help you as much as possible.

Why Routing?

Good question, Angular is defined as a single-page applications framework. However, Routing is recognized as a significant enhancement for the user experience. What’s more, you could use Guards, Resolvers which allows you to respect the separation of concerns more and greatly simplify your code.

By using lazy loading modules, you will maximize the performance of your application.

Anyway, we will talk about all of these points here in other chapters. I suggest starting this article with the basis.

Basic Routing

Default routing module generated on project creation

By default, when you create an Angular application without specifying options, you get by default the app-routing.module.ts.

_import_ { NgModule } _from_ '@angular/core';
_import_ { RouterModule, _Routes_ } _from_ '@angular/router';

_const_ routes: _Routes_ = []; (1)

@NgModule({
  imports: [RouterModule._forRoot_(routes)], (2)
  exports: [RouterModule]
})
_export class_ AppRoutingModule {}
Enter fullscreen mode Exit fullscreen mode

This module is imported in your app.module.ts .

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, **AppRoutingModule** , ...], (3)
  bootstrap: [AppComponent]
})
_export class_ AppModule {
}
Enter fullscreen mode Exit fullscreen mode

And in the app.component.html, you have this (probably after the default generated code):

<router-outlet></router-outlet> (4)
Enter fullscreen mode Exit fullscreen mode

Maybe we could just make a stop here to explain some points.

  • Routes is just a type that corresponds to Route[] .
_export declare type Routes_ = _Route_[];
Enter fullscreen mode Exit fullscreen mode

The route is an interface that defines requirements to represent a route. We will see all properties step by step.

  • We use the RouterModule.forRoot first to import the module that handles the routing feature and give it which routes we have defined (none yet). It’s essential to use the forRoot because it’s the root’s routing definition of our application.
  • Don’t forget to import the routing module in the associated feature module.
  • RouterOutlet is the directive defined by Angular, which acts as a placeholder and is filled by Angular depending on the current router state.

Okay, I hope to lose anyone but don’t worry, we will see all of that with examples.

Our first basic routes

Suppose we have two domains in our app called feature-1 and feature-2. We would like to have direct access to the respective URLs:

Both have their associated entry point component called Feature1Component and Feature2Component.

Here’s how to define simple routes:

// app-routing.module.ts

_const_ routes: _Routes_ = [
  {
    path: 'feature-1', component: Feature1Component,
  }, {
    path: 'feature-2', component: Feature2Component,
  }
];
Enter fullscreen mode Exit fullscreen mode

Now you can directly access the desired URLs (http://localhost:4200/feature-1, http://localhost:4200/feature-2).

Yes, but I would like to go directly on feature-1 when I enter http://localhost:4200.

You are right, and we need to define a default root.

// app-routing.module.ts

_const_ routes: _Routes_ = [
  {
    path: 'feature-1', component: Feature1Component,
  }, {
    path: 'feature-2', component: Feature2Component,
  }, {
    **path: '', pathMatch: 'full', redirectTo: 'feature-1',**
  }
];
Enter fullscreen mode Exit fullscreen mode

Here, we defined that we want to redirect to the feature-1 way when there is no specified path. Don’t forget the pathMatch: ‘full,’ it allows us to indicate that we only want “no defined path” with the combination of the path.”

In HTML, we can use the URLs to get access to the pages:

<a _routerLink_="/feature-1">Feature 1</a>
<a _routerLink_="/feature-2">Feature 2</a>
Enter fullscreen mode Exit fullscreen mode

Tips: How to know if the link is active or not ? You can use the RouterLinkActive directive like this:

<a _routerLink_="/feature-1" routerLinkActive="myCssClass" [routerLinkActiveOptions]="{exact: true}">Feature 1</a>
Enter fullscreen mode Exit fullscreen mode

If the link matches exactly the current route, then the link will get the CSS class myCssClass. If the routerLinkActiveOptions: { exact: true } then it works like a match.

Route with children

Now, suppose that our feature-3 comprises two children sub-feature called sub-feature-3–1 and sub-feature-3–2 and not directly represented by one component as previously.

// app-routing.module.ts

_const_ routes: _Routes_ = [
  {
    path: 'feature-1', component: Feature1Component
  }, {
    path: 'feature-2', component: Feature2Component,
  }, **{  
 path: 'feature-3', children: [  
 {  
 path: 'sub-feature-3-1',  
 component: Subfeature31Component  
 }, {  
 path: 'sub-feature-3-2',  
 component: Subfeature32Component  
 }, {  
 path: '',  
 redirectTo: 'sub-feature-3-1',  
 pathMatch: 'full' _// don't forget it_  
}  
 ]  
 }** , {
    path: '', pathMatch: 'full', redirectTo: 'feature-1'
  }
];
Enter fullscreen mode Exit fullscreen mode

And in HTML:

<a _routerLink_="/feature-1">Feature 1</a>
<a _routerLink_="/feature-2">Feature 2</a>
<a _routerLink_="/feature-3">Sub Feature 3 1</a> <!-- Simplified there is a redirectTo -->
<a _routerLink_="/feature-3/sub-feature-3-2">Sub Feature 3 2</a>
Enter fullscreen mode Exit fullscreen mode

Router service

The Router service provides navigation information and can be used to navigate from an URL to another one.

Tips: You can tracing all routing events if you want to debug and understand what is done during navigation:

@NgModule({
  imports: [RouterModule._forRoot_(routes, {
    enableTracing: !environment.production // just in dev mode
  })],
  exports: [RouterModule]
})
_export class_ AppRoutingModule {
}
Enter fullscreen mode Exit fullscreen mode

If you want to navigate with the Router service, you just have to do this :

_this_.router.navigateByUrl('/feature-2');

or

_this_.router.navigate(['/feature-2']);
Enter fullscreen mode Exit fullscreen mode

If you want to display a loading spinner during the navigation you can do something like:

// in app.component.ts

_private_ _isLoading$: BehaviorSubject<_boolean_> = _new_ BehaviorSubject<_boolean_>(_false_);

_constructor_(_private_ router: Router) {
}

_public_ ngOnInit(): _void_ {
  _this_.router.events.pipe(
    _filter_((event: _Event_) => event _instanceof_ NavigationStart)
  ).subscribe(() => _this_._isLoading$.next(_true_));

  _this_.router.events.pipe(
    _filter_((event: _Event_) => event _instanceof_ NavigationEnd)
  ).subscribe(() => _this_._isLoading$.next(_false_));
}
Enter fullscreen mode Exit fullscreen mode

Define a 404 page

How to handle an unexisting URL in your application?

Once again, Angular provided for it. You can define a wildcard route like this:

// app-routing.module.ts

{
  path: '**', component: PageNotFoundComponent
}
Enter fullscreen mode Exit fullscreen mode

It means that if no route corresponds to the current requested URL then the displayed component will be PageNotFoundComponent.

Conclusion

Now you should be able to use routing in your application. Just tell me if you don’t. I know you are a bit frustrated, but I promise to quickly write articles about guards, resolvers, nested routes, and lazy loading ASAP.

Here you can access my project I use for medium articles:

GitHub - GaetanRdn/medium-angular: This project is a support for my medium articles.

Thanks for reading!

Learn More

Angular for everyone: All about it

Discussion (0)