Let us start day 9 of the "Learning Angular 4.0 in 10 Days" series. In the previous articles, we discussed Ajax Request handling in Angular 4.0. If you want to read the previous articles of this series, do visit the below links.
Angular 4.0 brings many improved modules to the Angular framework including a new router called the Component Router. The component router is a totally configurable and feature-packed router. Features included are standard view routing, nested child routes, named routes and route parameters.
Why Routing?
Routing allows us to specify some aspects of the application's state in the URL. Unlike with server-side front-end solutions, this is optional - we can build the full application without ever changing the URL. Adding routing, however, allows the user to go straight into certain aspects of the application. This is very convenient as it can keep your application linkable and bookmarkable and allow users to share links with others.
Routing allows you to,
- Maintain the state of the application
- Implement modular applications
- Implement the application based on the roles (certain roles have access to certain URLs)
Route Definition Objects
The Routes type is an array of routes, that defines the routing for the application. This is where we can set up the expected paths, the components we want to use and what we want our application to understand them as.
Each route can have different attributes; some of the common attributes are,
- path - URL to be shown in the browser when the application is on the specific route
- component - component to be rendered when the application is on the specific route
- redirectTo - redirect route if needed; each route can have either component or redirect attribute defined in the route (covered later in this chapter)
- pathMatch - optional property that defaults to 'prefix'; determines whether to match full URLs or just the beginning. When defining a route with empty path string set pathMatch to 'full', otherwise it will match all paths.
- children - an array of route definitions objects representing the child routes of this route (covered later in this chapter)
To use Routes, create an array of route configurations.
We then import our routing configuration in the root of our application.
- import { routing } from './app.routes';
-
- @NgModule({
- imports: [
- BrowserModule,
- routing
- ],
- declarations: [
- AppComponent,
- ComponentOne,
- ComponentTwo
- ],
- bootstrap: [ AppComponent ]
- })
- export class AppModule {
- }
Redirecting the Router to Another Route
When your application starts, it navigates to the empty route by default. We can configure the router to redirect to a named route by default,
- export const routes: Routes = [
- { path: '', redirectTo: 'component-one', pathMatch: 'full' },
- { path: 'component-one', component: ComponentOne },
- { path: 'component-two', component: ComponentTwo }
- ];
The pathMatch property, which is required for redirects, tells the router how it should match the URL provided in order to redirect to the specified route. Since pathMatch: full is provided, the router will redirect to component-one if the entire URL matches the empty path ('').
When starting the application, it will now automatically navigate to the route for component one.
RouterLink
Add links to routes using the RouterLink directive. For example the following code defines a link to the route at path component-one.
- <a routerLink="/component-one">Component One</a>
Alternatively, you can navigate to a route by calling the navigate function on the router:
- this.router.navigate(['/component-one']);
Dynamically Adding Route Components
Rather than define each route's component separately, use RouterOutlet which serves as a component placeholder; Angular dynamically adds the component for the route being activated into the <router-outlet></router-outlet> element.
- <router-outlet></router-outlet>
In the above example, the component corresponding to the route specified will be placed after the <router-outlet></router-outlet> element when the link is clicked.
What are Nested Child Routes?
Child/Nested routing is a powerful new feature in the new Angular router. We can think of our application as a tree structure, components nested in more components. We can think the same way with our routes and URLs.
So we have the following routes, / and /about. Maybe our about page is extensive and there are a couple of different views we would like to display as well. The URLs would look something like /about and /about/item. The first route would be the default about page but more routes would offer another view with more details.
Defining Child Routes
When some routes may only be accessible and viewed within other routes it may be appropriate to create them as child routes.
For example: The product details page may have a tabbed navigation section that shows the product overview by default. When the user clicks the "Technical Specs" tab the section shows the specs instead.
If the user clicks on the product with ID 3, we want to show the product details page with the overview:
localhost:3000/product-details/3/overview
When the user clicks "Technical Specs":
localhost:3000/product-details/3/specs
overview and specs are child routes of product-details/:id. They are only reachable within product details.
Passing Optional Parameters
Query parameters allow you to pass optional parameters to a route such as pagination information.
For example, on a route with a paginated list, the URL might look like the following to indicate that we've loaded the second page:
localhost:3000/product-list?page=2
The key difference between query parameters and route parameters is that the route parameters are essential to determining a route, whereas query parameters are optional.
Passing Query Parameters
Use the [queryParams] directive along with [routerLink] to pass query parameters. For example,
- <a [routerLink]="['product-list']" [queryParams]="{ page: 99 }">Go to Page 99</a>
Alternatively, we can navigate programmatically using the Router service.
- goToPage(pageNum) {
- this.router.navigate(['/product-list'], { queryParams: { page: pageNum } });
- }
Reading Query Parameters
Similar to reading route parameters, the Router service returns an Observable we can subscribe to in order to read the query parameters.
- import { Component } from '@angular/core';
- import { ActivatedRoute, Router } from '@angular/router';
-
- @Component({
- selector: 'product-list',
- template: `<!-- Show product list -->`
- })
- export default class ProductList {
- constructor(
- private route: ActivatedRoute,
- private router: Router) {}
-
- ngOnInit() {
- this.sub = this.route
- .queryParams
- .subscribe(params => {
-
- this.page = +params['page'] || 0;
- });
- }
-
- ngOnDestroy() {
- this.sub.unsubscribe();
- }
-
- nextPage() {
- this.router.navigate(['product-list'], { queryParams: { page: this.page + 1 } });
- }
- }
Sample Code of app.staticroute.module.ts
- import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
- import { APP_BASE_HREF } from '@angular/common';
- import { BrowserModule } from '@angular/platform-browser';
- import { FormsModule } from "@angular/forms";
-
- import { routing, appRoutingProviders } from './day4/route/route_config/static/app.routes';
- import { HomePageComponent } from './day4/route/route_config/static/app.component.homepage';
- import { HomeComponent } from './day4/route/route_config/static/app.component.home';
- import { FirstProgComponent } from './day1/component/app.component.firstprog';
- import { HelloWorldComponent } from './day1/component/app.component.helloworld';
- import { TemplateUrlStyleComponent } from './day1/component/app.component.templatestyle';
-
-
- @NgModule({
- imports: [BrowserModule, FormsModule, routing],
- declarations: [HomePageComponent, HomeComponent, HelloWorldComponent, FirstProgComponent, TemplateUrlStyleComponent],
- bootstrap: [HomePageComponent],
- schemas: [NO_ERRORS_SCHEMA],
- providers: [{ provide: APP_BASE_HREF, useValue: '/' }, appRoutingProviders],
- })
-
- export class StaticRouteModule { }
Sample Code of main.ts
- import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
- import { StaticRouteModule } from './app.staticroute.module';
-
-
- platformBrowserDynamic().bootstrapModule(StaticRouteModule);
Sample Code of app.staticroute.module.html
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <!--<base href="/">-->
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <meta charset="utf-8">
- <title>Angular 2 - Console</title>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="">
- <meta name="keywords" content="">
- <meta name="author" content="">
-
- <link href="resource/css/bootstrap.min.css" rel="stylesheet">
- <link rel="stylesheet" href="resource/css/font-awesome.min.css">
- <link rel="stylesheet" href="resource/css/jquery-ui.css">
- <link href="resource/css/style.css" rel="stylesheet">
- </head>
- <body>
- <home-page></home-page>
- <footer>
- <div class="container">
- <div class="row">
- <div class="col-md-12">
- <p class="copy">Copyright © 2017-2018 | <a href="http://www.c-sharpcorner.com/members/debasis-saha">Debasis Saha</a> </p>
- </div>
- </div>
- </div>
- </footer>
- <script src="resource/js/jquery.js"></script>
- <script src="resource/js/bootstrap.min.js"></script>
- <script src="resource/js/jquery-ui.min.js"></script>
- <script src="resource/js/jquery.slimscroll.min.js"></script>
- <script src="resource/js/custom.js"></script>
-
- <script src="node_modules/core-js/client/shim.min.js"></script>
- <script src="node_modules/zone.js/dist/zone.js"></script>
- <script src="node_modules/systemjs/dist/system.src.js"></script>
- <script src="systemjs.config.js"></script>
- <script>
- System.import('main.js').catch(function (err) { console.error(err); });
- </script>
-
- <!-- Set the base href, demo only! In your app: <base href="/"> -->
- <script>document.write('<base href="' + document.location + '" />');</script>
- </body>
- </html>
Sample Code of app.component.home.ts
- import { Component, OnInit, ViewChild } from '@angular/core';
-
- @Component({
- moduleId: module.id,
- selector: 'home',
- template: 'Angular Samples Home Page'
- })
-
- export class HomeComponent implements OnInit {
- constructor() {
-
- }
-
- ngOnInit(): void {
- }
-
- }
Sample Code of app.component.homepage.ts
- import { Component, OnInit } from '@angular/core';
-
- @Component({
- moduleId: module.id,
- selector: 'home-page',
- templateUrl: 'app.component.homepage.html'
- })
-
- export class HomePageComponent implements OnInit {
-
- constructor() {
- }
-
- ngOnInit(): void {
- }
-
- }
Sample Code of app.routes.ts
- import { Routes, RouterModule } from '@angular/router';
- import { HomeComponent } from './app.component.home';
- import { FirstProgComponent } from '../../../../day1/component/app.component.firstprog';
- import { HelloWorldComponent } from '../../../../day1/component/app.component.helloworld';
- import { TemplateUrlStyleComponent } from '../../../../day1/component/app.component.templatestyle';
-
-
- export const routes: Routes = [
- { path: '', redirectTo: 'home', pathMatch: 'full' },
- { path: 'home', component: HomeComponent },
- { path: 'hello', component: HelloWorldComponent },
- { path: 'firstprog', component: FirstProgComponent },
- { path: 'template', component: TemplateUrlStyleComponent }
-
- ];
-
- export const appRoutingProviders: any[] = [];
-
- export const routing = RouterModule.forRoot(routes);
Sample Code of app.component.firstprog.ts
- import { Component } from "@angular/core";
-
- @Component({
- selector: "first-prog",
- template: "<h1>First Programe in Angular 4.0. Welcome to Day 1 Session</h1> "
- })
-
- export class FirstProgComponent {
- constructor() {
- }
- }
Sample Code of app.component.helloworld.ts
- import { Component } from '@angular/core';
-
- @Component({
- selector: 'hello-world',
- template: '<h1><b>Angular 4!</b>Hello World</h1>'
- })
-
- export class HelloWorldComponent {
- constructor() {
- }
-
- ngOnInit() {
- alert("Page Init Method Fired!!")
- }
- }
Sample Code of app.component.templatestyle.ts
- import { Component } from '@angular/core';
-
- @Component({
- moduleId: module.id,
- selector: 'template-style',
- templateUrl: 'app.component.template.html',
- styles: ['h1{color:red;font-weight:bold}','h2{color:blue}']
- })
-
- export class TemplateUrlStyleComponent {
- constructor() {
-
- }
- }
Sample Code of app.component.template.html
- <div>
- <h1>Angular 4 Component with Template</h1>
- <br />
- <h2>C# Corner</h2>
- </div>