Home >Web Front-end >JS Tutorial >Angular Router: An Introduction to Component Routing
This is part 4 of the SitePoint Angular 2 Tutorial on how to create a CRUD App with the Angular CLI. In this article, we’ll introduce Angular Router and learn how it can update our application when the browser URL changes and vice versa. We’ll also learn how we can update our application to resolve data from our back-end API using the router.
In part one we learned how to get our Todo application up and running and deploy it to GitHub pages. This worked just fine but, unfortunately, the whole app was crammed into a single component.
In part two we examined a more modular component architecture and learned how to break this single component into a structured tree of smaller components that are easier to understand, reuse and maintain.
In part three we updated our application to communicate with a REST API back end using RxJS and Angular’s HTTP service.
Don’t worry! You don’t need to have followed part one, two or three of this tutorial, for four to make sense. You can simply grab a copy of our repo, checkout the code from part three, and use that as a starting point. This is explained in more detail below.
Make sure you have the latest version of the Angular CLI installed. If you don’t, you can install it with the following command:
<span>npm install -g @angular/cli@latest </span>
If you need to remove a previous version of the Angular CLI, you can do this:
npm uninstall -g @angular/cli angular-cli npm cache clean <span>npm install -g @angular/cli@latest </span>
After that, you’ll need a copy of the code from part three. This is available at GitHub. Each article in this series has a corresponding tag in the repository so you can switch back and forth between the different states of the application.
The code that we ended with in part three and that we start with in this article is tagged as part-3. The code that we end this article with is tagged as part-4.
You can think of tags like an alias to a specific commit id. You can switch between them using git checkout. You can read more on that here.
So, to get up and running (the latest version of the Angular CLI installed) we would do this:
<span>git clone git@github.com:sitepoint-editors/angular-todo-app.git </span><span>cd angular-todo-app </span><span>git checkout part-3 </span><span>npm install </span>ng serve
Then visit http://localhost:4200/. If all’s well, you should see the working Todo app.
Here’s what our application architecture looked like at the end of part 3:
In this article we will:
By the end of this article, you’ll understand:
So, let’s get started!
In its current state, our web application does not take the browser URL into account.
We access our application through one URL such as http://localhost:4200 and our application is not aware of any other URLs such as http://localhost:4200/todos.
Most web applications need to support different URLs to navigate users to different pages in the application. That’s where a router comes in.
In traditional websites, routing is handled by a router on the server:
In modern JavaScript web applications, routing is often handled by a JavaScript router in the browser.
In essence, a JavaScript router does two things:
JavaScript routers make it possible for us to develop single-page applications (SPAs).
An SPA is a web application that provides a user experience similar to a desktop application. In an SPA, all communication with a back end occurs behind the scenes.
When a user navigates from one page to another, the page is updated dynamically without reload, even if the URL changes.
There are many different JavaScript router implementations available.
Some of them are specifically written for a certain JavaScript framework such as Angular, Ember, React, Vue.js and Aurelia, etc. Other implementations are built for generic purposes and aren’t tied to a specific framework.
Angular Router is an official Angular routing library, written and maintained by the Angular Core Team.
It’s a JavaScript router implementation that’s designed to work with Angular and is packaged as @angular/router.
First of all, Angular Router takes care of the duties of a JavaScript router:
In addition, Angular Router allows us to:
In this article, we’ll learn how to set up and configure Angular Router, how to redirect a URL and how to use Angular Router to resolve todos from our back-end API.
In the next article, we’ll add authentication to our application and use the router to make sure some of the pages can only be accessed when the user is signed in.
Before we dive into the code, it’s important to understand how Angular Router operates and the terminology it introduces.
When a user navigates to a page, Angular Router performs the following steps in order:
To accomplish its tasks, Angular Router introduces the following terms and concepts:
Don’t worry if the terminology sounds overwhelming. You’ll get used to the terms as we tackle them gradually in this series and as you gain more experience with Angular Router.
An Angular application that uses Angular Router only has one router service instance: It’s a singleton. Whenever and wherever you inject the Router service in your application, you’ll get access to the same Angular Router service instance.
For a more in-depth look at Angular routing process, make sure to check out the 7-step routing process of Angular Router navigation.
To enable routing in our Angular application, we need to do three things:
So let’s start by creating a routing configuration.
To create our routing configuration, we need a list of the URLs we’d like our application to support.
Currently, our application is very simple and only has one page that shows a list of todos:
which would show the list of todos as the home page of our application.
However, when a user bookmarks / in their browser to consult their list of todos and we change the contents of our home page (which we’ll do in part 5 of this series), their bookmark would no longer show their list of todos.
So let’s give our todo list its own URL and redirect our home page to it:
This provides us with two benefits:
The official Angular style guide recommends storing the routing configuration for an Angular module in a file with a filename ending in -routing.module.ts that exports a separate Angular module with a name ending in RoutingModule.
Our current module is called AppModule, so we create a file src/app/app-routing.module.ts and export our routing configuration as an Angular module called AppRoutingModule:
<span>npm install -g @angular/cli@latest </span>
First we import RouterModule and Routes from @angular/router:
npm uninstall -g @angular/cli angular-cli npm cache clean <span>npm install -g @angular/cli@latest </span>
Next, we define a variable routes of type Routes and assign it our router configuration:
<span>git clone git@github.com:sitepoint-editors/angular-todo-app.git </span><span>cd angular-todo-app </span><span>git checkout part-3 </span><span>npm install </span>ng serve
The Routes type is optional and lets an IDE with TypeScript support or the TypeScript compiler conveniently validate your route configuration during development.
The router configuration represents all possible router states our application can be in.
It is a tree of routes, defined as a JavaScript array, where each route can have the following properties:
Our application is simple and only contains two sibling routes, but a larger application could have a router configuration with child routes such as:
<span>import { NgModule } from '@angular/core'; </span><span>import { RouterModule, Routes } from '@angular/router'; </span><span>import { AppComponent } from './app.component'; </span> <span>const routes: Routes = [ </span> <span>{ </span> path<span>: '', </span> redirectTo<span>: 'todos', </span> pathMatch<span>: 'full' </span> <span>}, </span> <span>{ </span> path<span>: 'todos', </span> component<span>: AppComponent </span> <span>} </span><span>]; </span> <span><span>@NgModule</span>({ </span> imports<span>: [RouterModule.forRoot(routes)], </span> exports<span>: [RouterModule], </span> providers<span>: [] </span><span>}) </span><span>export class AppRoutingModule { </span><span>} </span>
Here, todos has two child routes and :id is a route parameter, enabling the router to recognize the following URLs:
Notice how we specify pathMatch: 'full' when defining the redirect.
Angular Router has two matching strategies:
We can create the following route:
<span>import { RouterModule, Routes } from '@angular/router'; </span>
In this case, Angular Router applies the default prefix path matching strategy and every URL is redirected to todos because every URL starts with the empty string '' specified in path.
We only want our home page to be redirected to todos , so we add pathMatch: 'full' to make sure that only the URL that equals the empty string '' is matched:
<span>npm install -g @angular/cli@latest </span>
To learn more about the different routing configuration options, check out the official Angular documentation on Routing and Navigation.
Finally, we create and export an Angular module AppRoutingModule:
npm uninstall -g @angular/cli angular-cli npm cache clean <span>npm install -g @angular/cli@latest </span>
There are two ways to create a routing module:
The RouterModule.forChild() method is needed when your application has multiple routing modules.
Remember that the router service takes care of synchronization between our application state and the browser URL. Instantiating multiple router services that interact with the same browser URL would lead to issues, so it is essential that there’s only one instance of the router service in our application, no matter how many routing modules we import in our application.
When we import a routing module that is created using RouterModule.forRoot(), Angular will instantiate the router service. When we import a routing module that’s created using RouterModule.forChild(), Angular will not instantiate the router service.
Therefore we can only use RouterModule.forRoot() once and use RouterModule.forChild() multiple times for additional routing modules.
Because our application only has one routing module, we use RouterModule.forRoot():
<span>git clone git@github.com:sitepoint-editors/angular-todo-app.git </span><span>cd angular-todo-app </span><span>git checkout part-3 </span><span>npm install </span>ng serve
In addition, we also specify RouterModule in the exports property:
<span>import { NgModule } from '@angular/core'; </span><span>import { RouterModule, Routes } from '@angular/router'; </span><span>import { AppComponent } from './app.component'; </span> <span>const routes: Routes = [ </span> <span>{ </span> path<span>: '', </span> redirectTo<span>: 'todos', </span> pathMatch<span>: 'full' </span> <span>}, </span> <span>{ </span> path<span>: 'todos', </span> component<span>: AppComponent </span> <span>} </span><span>]; </span> <span><span>@NgModule</span>({ </span> imports<span>: [RouterModule.forRoot(routes)], </span> exports<span>: [RouterModule], </span> providers<span>: [] </span><span>}) </span><span>export class AppRoutingModule { </span><span>} </span>
This ensures that we don’t have to explicitly import RouterModule again in AppModule when AppModule imports AppRoutingModule.
Now that we have our AppRoutingModule, we need to import it in our AppModule to enable it.
To import our routing configuration into our application, we must import AppRoutingModule into our main AppModule.
Let’s open up src/app/app.module.ts and add AppRoutingModule to the imports array in AppModule’s @NgModule metadata:
<span>import { RouterModule, Routes } from '@angular/router'; </span>
Because AppRoutingModule has RoutingModule listed in its exports property, Angular will import RoutingModule automatically when we import AppRoutingModule, so we don’t have to explicitly import RouterModule again (although doing so would not cause any harm).
Before we can try out our changes in the browser, we need to complete the third and final step.
Although our application now has a routing configuration, we still need to tell Angular Router where it can place the instantiated components in the DOM.
When our application is bootstrapped, Angular instantiates AppComponent because AppComponent is listed in the bootstrap property of AppModule:
<span>npm install -g @angular/cli@latest </span>
To tell Angular Router where it can place components, we must add the
The
If you’re familiar AngularJS 1.x router and UI-Router, you can consider
Without a
AppComponent currently displays a list of todos.
But instead of letting AppComponent display a list of todos, we now want AppComponent to contain a
To accomplish that, let’s generate a new component TodosComponent using Angular CLI:
npm uninstall -g @angular/cli angular-cli npm cache clean <span>npm install -g @angular/cli@latest </span>
Let’s also move all HTML from src/app/app.component.html to src/app/todos/todos.component.html:
<span>git clone git@github.com:sitepoint-editors/angular-todo-app.git </span><span>cd angular-todo-app </span><span>git checkout part-3 </span><span>npm install </span>ng serve
Let’s also move all logic from src/app/app.component.ts to src/app/todos/todos.component.ts:
<span>import { NgModule } from '@angular/core'; </span><span>import { RouterModule, Routes } from '@angular/router'; </span><span>import { AppComponent } from './app.component'; </span> <span>const routes: Routes = [ </span> <span>{ </span> path<span>: '', </span> redirectTo<span>: 'todos', </span> pathMatch<span>: 'full' </span> <span>}, </span> <span>{ </span> path<span>: 'todos', </span> component<span>: AppComponent </span> <span>} </span><span>]; </span> <span><span>@NgModule</span>({ </span> imports<span>: [RouterModule.forRoot(routes)], </span> exports<span>: [RouterModule], </span> providers<span>: [] </span><span>}) </span><span>export class AppRoutingModule { </span><span>} </span>
Now we can replace AppComponent’s template in src/app/app.component.html with:
<span>import { RouterModule, Routes } from '@angular/router'; </span>
We can also remove all obsolete code from AppComponent’s class in src/app/app.component.ts:
<span>const routes: Routes = [ </span> <span>{ </span> path<span>: '', </span> redirectTo<span>: 'todos', </span> pathMatch<span>: 'full' </span> <span>}, </span> <span>{ </span> path<span>: 'todos', </span> component<span>: AppComponent </span> <span>} </span><span>]; </span>
Finally, we update our todos route in src/app/app-routing.module.ts to instantiate TodosComponent instead of AppComponent:
<span>const routes: Routes = [ </span> <span>{ </span> path<span>: '', </span> redirectTo<span>: 'todos', </span> pathMatch<span>: 'full' </span> <span>}, </span> <span>{ </span> path<span>: 'todos', </span> children<span>: [ </span> <span>{ </span> path<span>: '', </span> component<span>: 'TodosPageComponent' </span> <span>}, </span> <span>{ </span> path<span>: ':id', </span> component<span>: 'TodoPageComponent' </span> <span>} </span> <span>] </span> <span>} </span><span>]; </span>
Now, when our application is bootstrapped, Angular instantiates AppComponent and finds a
Let’s try out our changes in the browser.
Start your development server and your back-end API by running:
<span>// no pathMatch specified, so Angular Router applies </span><span>// the default `prefix` pathMatch </span><span>{ </span> path<span>: '', </span> redirectTo<span>: 'todos' </span><span>} </span>
Then navigate your browser to http://localhost:4200.
Angular Router reads the router configuration and automatically redirects our browser to http://localhost:4200/todos.
If you inspect the elements on the page, you’ll see that the TodosComponent is not rendered inside
<span>{ </span> path<span>: '', </span> redirectTo<span>: 'todos', </span> pathMatch<span>: 'full' </span><span>} </span>
Our application now has routing enabled. Awesome!
When you navigate your browser to http://localhost:4200/unmatched-url, and you open up your browser’s developer tools, you will notice that Angular Router logs the following error to the console:
<span><span>@NgModule</span>({ </span> imports<span>: [RouterModule.forRoot(routes)], </span> exports<span>: [RouterModule], </span> providers<span>: [] </span><span>}) </span><span>export class AppRoutingModule { </span><span>} </span>
To handle unmatched URLs gracefully we need to do two things:
Let’s start by generating PageNotFoundComponent using Angular CLI:
<span>npm install -g @angular/cli@latest </span>
Then edit its template in src/app/page-not-found/page-not-found.component.html:
npm uninstall -g @angular/cli angular-cli npm cache clean <span>npm install -g @angular/cli@latest </span>
Next, we add a wildcard route using ** as a path:
<span>git clone git@github.com:sitepoint-editors/angular-todo-app.git </span><span>cd angular-todo-app </span><span>git checkout part-3 </span><span>npm install </span>ng serve
The ** matches any URL, including child paths.
Now, if you navigate your browser to http://localhost:4200/unmatched-url, PageNotFoundComponent is displayed.
Notice that the wildcard route must be the last route in our routing configuration for it to work as expected.
When Angular Router matches a request URL to the router configuration, it stops processing as soon as it finds the first match.
So if we were to change the order of the routes to this:
<span>import { NgModule } from '@angular/core'; </span><span>import { RouterModule, Routes } from '@angular/router'; </span><span>import { AppComponent } from './app.component'; </span> <span>const routes: Routes = [ </span> <span>{ </span> path<span>: '', </span> redirectTo<span>: 'todos', </span> pathMatch<span>: 'full' </span> <span>}, </span> <span>{ </span> path<span>: 'todos', </span> component<span>: AppComponent </span> <span>} </span><span>]; </span> <span><span>@NgModule</span>({ </span> imports<span>: [RouterModule.forRoot(routes)], </span> exports<span>: [RouterModule], </span> providers<span>: [] </span><span>}) </span><span>export class AppRoutingModule { </span><span>} </span>
then todos would never be reached and PageNotFoundComponent would be displayed because the wildcard route would be matched first.
We have already done a lot, so let’s quickly recap what we have accomplished so far:
Next, we will create a resolver to fetch the existing todos from our back-end API using Angular Router.
In the part 3 of this series we already learned how to fetch data from our back-end API using the Angular HTTP service.
Currently, when we navigate our browser to the todos URL, the following happens:
If loading the todos in step 5 takes three seconds, the user will be presented with an empty todo list for three seconds before the actual todos are displayed in step 6.
If the TodosComponent were to have the following HTML in its template:
<span>import { RouterModule, Routes } from '@angular/router'; </span>
then the user would see this message for three seconds before the actual todos are displayed, which could totally mislead the user and cause the user to navigate away before the actual data comes in.
We could add a loader to TodosComponent that shows a spinner while the data is being loaded, but sometimes we may not have control over the actual component, for example when we use a third-party component.
To fix this unwanted behavior, we need the following to happen:
Here, the TodosComponent is not displayed until the data from our API back end is available.
That is exactly what a resolver can do for us.
To let Angular Router resolve the todos before it activates the TodosComponent, we must do two things:
By attaching a resolver to the todos route we ask Angular Router to resolve the data first, before TodosComponent is activated.
So let’s create a resolver to fetch our todos.
Angular CLI does not have a command to generate a resolver, so let’s create a new file src/todos.resolver.ts manually and add the following code:
<span>npm install -g @angular/cli@latest </span>
We define the resolver as a class that implements the Resolve interface.
The Resolve interface is optional, but lets our TypeScript IDE or compiler ensure that we implement the class correctly by requiring us to implement a resolve() method.
When Angular Router needs to resolve data using a resolver, it calls the resolver’s resolve() method and expects the resolve() method to return a value, a promise, or an observable.
If the resolve() method returns a promise or an observable Angular Router will wait for the promise or observable to complete before it activates the route’s component.
When calling the resolve() method, Angular Router conveniently passes in the activated route snapshot and the router state snapshot to provide us with access to data (such as route parameters or query parameters) we may need to resolve the data.
The code for TodosResolver is very concise because we already have a TodoDataService that handles all communication with our API back end.
We inject TodoDataService in the constructor and use its getAllTodos() method to fetch all todos in the resolve() method.
The resolve method returns an observable of the type Todo[], so Angular Router will wait for the observable to complete before the route’s component is activated.
Now that we have our resolver, let’s configure Angular Router to use it.
To make Angular Router use a resolver, we must attach it to a route in our route configuration.
Let’s open up src/app-routing.module.ts and add our TodosResolver to the todos route:
<span>npm install -g @angular/cli@latest </span>
We import TodosResolver:
npm uninstall -g @angular/cli angular-cli npm cache clean <span>npm install -g @angular/cli@latest </span>
Also add it as a resolver the the todos route:
<span>git clone git@github.com:sitepoint-editors/angular-todo-app.git </span><span>cd angular-todo-app </span><span>git checkout part-3 </span><span>npm install </span>ng serve
This tells Angular Router to resolve data using TodosResolver and assign the resolver’s return value as todos in the route’s data.
A route’s data can be accessed from the ActivatedRoute or ActivatedRouteSnapshot, which we will see in the next section.
You can add static data directly to a route’s data using the data property of the route:
<span>import { NgModule } from '@angular/core'; </span><span>import { RouterModule, Routes } from '@angular/router'; </span><span>import { AppComponent } from './app.component'; </span> <span>const routes: Routes = [ </span> <span>{ </span> path<span>: '', </span> redirectTo<span>: 'todos', </span> pathMatch<span>: 'full' </span> <span>}, </span> <span>{ </span> path<span>: 'todos', </span> component<span>: AppComponent </span> <span>} </span><span>]; </span> <span><span>@NgModule</span>({ </span> imports<span>: [RouterModule.forRoot(routes)], </span> exports<span>: [RouterModule], </span> providers<span>: [] </span><span>}) </span><span>export class AppRoutingModule { </span><span>} </span>
You can also add dynamic data using a resolver specified in the the resolve property of the route:
<span>import { RouterModule, Routes } from '@angular/router'; </span>
You could also do both at the same time:
<span>const routes: Routes = [ </span> <span>{ </span> path<span>: '', </span> redirectTo<span>: 'todos', </span> pathMatch<span>: 'full' </span> <span>}, </span> <span>{ </span> path<span>: 'todos', </span> component<span>: AppComponent </span> <span>} </span><span>]; </span>
As soon as the resolvers from the resolve property are resolved, their values are merged with the static data from the data property and all data is made available as the route’s data.
Angular Router uses Angular dependency injection to access resolvers, so we have to make sure we register TodosResolver with Angular’s dependency injection system by adding it to the providers property in AppRoutingModule’s @NgModule metadata:
<span>const routes: Routes = [ </span> <span>{ </span> path<span>: '', </span> redirectTo<span>: 'todos', </span> pathMatch<span>: 'full' </span> <span>}, </span> <span>{ </span> path<span>: 'todos', </span> children<span>: [ </span> <span>{ </span> path<span>: '', </span> component<span>: 'TodosPageComponent' </span> <span>}, </span> <span>{ </span> path<span>: ':id', </span> component<span>: 'TodoPageComponent' </span> <span>} </span> <span>] </span> <span>} </span><span>]; </span>
When you navigate your browser to http://localhost:4200, Angular Router now:
If you open up the network tab of your developer tools, you’ll see that the todos are now fetched twice from the API. Once by Angular Router and once by the ngOnInit handler in TodosComponent.
So Angular Router already fetches the todos from the API, but TodosComponent still uses its own internal logic to load the todos.
In the next section, we’ll update TodosComponent to use the data resolved by Angular Router.
Let’s open up app/src/todos/todos.component.ts.
The ngOnInit() handler currently fetches the todos directly from the API:
<span>// no pathMatch specified, so Angular Router applies </span><span>// the default `prefix` pathMatch </span><span>{ </span> path<span>: '', </span> redirectTo<span>: 'todos' </span><span>} </span>
Now that Angular Router fetches the todos using TodosResolver, we want to fetch the todos in TodosComponent from the route data instead of the API.
To access the route data, we must import ActivatedRoute from @angular/router:
<span>{ </span> path<span>: '', </span> redirectTo<span>: 'todos', </span> pathMatch<span>: 'full' </span><span>} </span>
and use Angular dependency injection to get a handle of the activated route:
<span><span>@NgModule</span>({ </span> imports<span>: [RouterModule.forRoot(routes)], </span> exports<span>: [RouterModule], </span> providers<span>: [] </span><span>}) </span><span>export class AppRoutingModule { </span><span>} </span>
Finally, we update the ngOnInit() handler to get the todos from the route data instead of the API:
imports<span>: [RouterModule.forRoot(routes)] </span>
The ActivatedRoute exposes the route data as an observable, so our code barely changes.
We replace this.todoDataService.getAllTodos() with this.route.data.map((data) => data['todos']) and all the rest of the code remains unchanged.
If you navigate your browser to localhost:4200 and open up the network tab, you’ll no longer see two HTTP requests fetching the todos from the API.
Mission accomplished! We’ve successfully integrated Angular Router in our application!
Before we wrap up, let’s run our unit tests:
<span>npm install -g @angular/cli@latest </span>
One unit test fails:
npm uninstall -g @angular/cli angular-cli npm cache clean <span>npm install -g @angular/cli@latest </span>
When TodosComponent is tested, the testbed is not aware of TodoListHeaderComponent and thus Angular complains that it doesn’t know the app-todo-list-header element.
To fix this error, let’s open up app/src/todos/todos.component.spec.ts and add NO_ERRORS_SCHEMA to the TestBed options:
<span>git clone git@github.com:sitepoint-editors/angular-todo-app.git </span><span>cd angular-todo-app </span><span>git checkout part-3 </span><span>npm install </span>ng serve
Now Karma shows another error:
<span>import { NgModule } from '@angular/core'; </span><span>import { RouterModule, Routes } from '@angular/router'; </span><span>import { AppComponent } from './app.component'; </span> <span>const routes: Routes = [ </span> <span>{ </span> path<span>: '', </span> redirectTo<span>: 'todos', </span> pathMatch<span>: 'full' </span> <span>}, </span> <span>{ </span> path<span>: 'todos', </span> component<span>: AppComponent </span> <span>} </span><span>]; </span> <span><span>@NgModule</span>({ </span> imports<span>: [RouterModule.forRoot(routes)], </span> exports<span>: [RouterModule], </span> providers<span>: [] </span><span>}) </span><span>export class AppRoutingModule { </span><span>} </span>
Let’s add the necessary providers to the test bed options:
<span>import { RouterModule, Routes } from '@angular/router'; </span>
This again raises another error:
<span>const routes: Routes = [ </span> <span>{ </span> path<span>: '', </span> redirectTo<span>: 'todos', </span> pathMatch<span>: 'full' </span> <span>}, </span> <span>{ </span> path<span>: 'todos', </span> component<span>: AppComponent </span> <span>} </span><span>]; </span>
Let’s add one more provider for ActivatedRoute to the testbed options:
<span>const routes: Routes = [ </span> <span>{ </span> path<span>: '', </span> redirectTo<span>: 'todos', </span> pathMatch<span>: 'full' </span> <span>}, </span> <span>{ </span> path<span>: 'todos', </span> children<span>: [ </span> <span>{ </span> path<span>: '', </span> component<span>: 'TodosPageComponent' </span> <span>}, </span> <span>{ </span> path<span>: ':id', </span> component<span>: 'TodoPageComponent' </span> <span>} </span> <span>] </span> <span>} </span><span>]; </span>
We assign the provider for ActivatedRoute a mock object that contains an observable data property to expose a test value for todos.
Now the unit tests successfully pass:
<span>// no pathMatch specified, so Angular Router applies </span><span>// the default `prefix` pathMatch </span><span>{ </span> path<span>: '', </span> redirectTo<span>: 'todos' </span><span>} </span>
Fabulous! To deploy our application to a production environment, we can now run:
<span>{ </span> path<span>: '', </span> redirectTo<span>: 'todos', </span> pathMatch<span>: 'full' </span><span>} </span>
We upload the generated dist directory to our hosting server. How sweet is that?
We’ve covered a lot in this article, so let’s recap what we have learned.
In the first article, we learned how to:
In the second article, we refactored AppComponent to delegate most of its work to:
In the third article, we learned how to:
In this fourth article, we learned:
All code from this article is available at GitHub.
In part five, we’ll implement authentication to prevent unauthorized access to our application.
So stay tuned for more and, as always, feel free to leave your thoughts and questions in the comments!
Angular Router plays a crucial role in web development as it enables the creation of Single Page Applications (SPAs). SPAs are web applications or websites that interact with the user by dynamically rewriting the current web page with new data from the web server, instead of the default method of the browser loading entire new pages. This leads to a faster, more seamless user experience as only the necessary content is updated. Angular Router helps in defining the navigation paths among the different application states and manages the state transitions.
Angular Router provides a feature called wildcard routing to handle unknown or incorrect URLs. When the router encounters a URL that doesn’t match any predefined routes, it can redirect to a ‘404 Not Found’ page or any other fallback page. This is achieved by defining a route with the path ‘**’ and associating it with the desired component.
Yes, Angular Router allows passing data between routes using a feature called route parameters. Route parameters are parts of the URL that can change and their values can be used by the component to dynamically display content or determine behavior. This is particularly useful when you want to navigate to a detail view of an item in a list.
Angular Router provides a feature called route guards to protect certain routes in your application. Route guards are interfaces which can tell the router whether or not it should allow navigation to a requested route. They can be used to control access based on user authentication, role-based access control, or any other custom criteria.
Angular Router interacts with the browser’s history through the Location service. It uses the HTML5 history API to change the URL without causing a full page reload. This means that the back and forward buttons of the browser will work as expected, navigating between the application states.
Yes, Angular Router supports lazy loading of modules. This means that certain modules of your application can be loaded on demand, rather than at the initial load of the application. This can significantly improve the initial load performance of your application.
Angular Router provides a feature called router events which can be used to log and debug routing behavior. These events include navigation start, navigation end, route recognition, and many others. By subscribing to these events, you can get detailed information about the routing process.
Yes, Angular Router supports nested routes, also known as child routes. This allows you to create more complex navigation structures, where certain routes have sub-routes associated with them. This is particularly useful for creating hierarchical navigation structures.
Angular Router allows you to animate route transitions using Angular’s animation library. This can be used to create visually appealing transitions between different states of your application, enhancing the user experience.
Yes, Angular Router provides a feature called preloading strategy to preload modules. This means that certain modules can be loaded in the background, after the initial load of the application. This can significantly improve the navigation speed of your application, as the modules are already loaded when they are needed.
The above is the detailed content of Angular Router: An Introduction to Component Routing. For more information, please follow other related articles on the PHP Chinese website!