In this article, we will discuss the dynamic route concept in Angular 2.0. Before that, we first need to understand the requirement of routes in the AngularJS.
What is Routing?
Actually, Routing allows us to mention some aspects of the application's state in the URL. Using route concept in AngularJS, we can build our application for navigating different URLs or pages without changing the main URL of the application. 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 always allows us to,
- Maintain the state of the web application
- Implement modular applications so that we can navigate from one page to another page.
- Implement the application based on the roles (certain roles have access to certain URLs)
If you want to get the details of basic routing concept in Angular 2.0 then you can check the below articles of Angular 2 Series,
Why the need for Routing?
Normally, when we create a multiple page application or website, we always need to navigate among various pages or Views. With ASP.NET, we can do that using the window.redirect method. But in AngularJS, we can do this using a Single Page Application. Single Page Applications are becoming very popular today due to phone/tablet apps. AngularJS helps to easily create the applications like that.
Why is Dynamic Routing Required?
We can create routing static code using route data as mentioned in the above articles. This process is OK if our web application contains a limited number of pages or components. But, it becomes difficult when we have a large number of HTML files with components and we need to populate the navigation URL details depending on the user-defined rule, perhaps, just like menus in a web application. In those cases, we need t configure the routeconfig dynamically by reading the data from an outer soure file (in other words, from a database or JSON file) when we can change or rearrange the data as required.
For implementing this, we need to provide menu details including component name and route key from dynamic source like database or JSON file. So that, whenever we need to insert the new menu or link in the UI, we just need to insert the data into that JSON files so that the menu is automatically populated at the run time.
For this, open Visual Studio 2015 and create a blank project file with Wesite Application Type Projects. Now, include the below code as mentioned below -
tsconfig.json
- {
- "compileOnSave": true,
- "compilerOptions": {
- "target": "es5",
- "module": "commonjs",
- "moduleResolution": "node",
- "sourceMap": true,
- "emitDecoratorMetadata": true,
- "experimentalDecorators": true,
- "removeComments": false,
- "noImplicitAny": false
- },
- "exclude": [
- "node_modules"
- ]
- }
systemjs.config.js
- /**
- * System configuration for Angular samples
- * Adjust as necessary for your application needs.
- */
- (function (global) {
- System.config({
- paths: {
- // paths serve as alias
- 'npm:': 'node_modules/'
- },
- // map tells the System loader where to look for things
- map: {
- // our app is within the app folder
- 'app': '.',
-
- // angular bundles
- '@angular/animations': 'npm:@angular/animations/bundles/animations.umd.js',
- '@angular/animations/browser': 'npm:@angular/animations/bundles/animations-browser.umd.js',
- '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
- '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
- '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
- '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
- '@angular/platform-browser/animations': 'npm:@angular/platform-browser/bundles/platform-browser-animations.umd.js',
- '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
- '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
- '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
- '@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js',
- '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
- '@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js',
- '@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js',
-
- // other libraries
- 'rxjs': 'npm:rxjs',
- 'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
- },
- // packages tells the System loader how to load when no filename and/or no extension
- packages: {
- app: {
- main: './main.js',
- defaultExtension: 'js'
- },
- rxjs: {
- defaultExtension: 'js'
- }
- }
- });
- })(this);
package.json
- {
- "name": "Angular2_Sample",
- "version": "1.0.0",
- "scripts": {
- "start": "tsc && concurrently \"tsc -w\" \"lite-server\" ",
- "lite": "lite-server",
- "postinstall": "typings install",
- "tsc": "tsc",
- "tsc:w": "tsc -w",
- "typings": "typings"
- },
- "licenses": [
- {
- "type": "MIT",
- "url": "https://github.com/angular/angular.io/blob/master/LICENSE"
- }
- ],
- "dependencies": {
- "@angular/common": "~2.2.0",
- "@angular/compiler": "~2.2.0",
- "@angular/core": "~2.2.0",
- "@angular/forms": "~2.2.0",
- "@angular/http": "~2.2.0",
- "@angular/platform-browser": "~2.2.0",
- "@angular/platform-browser-dynamic": "~2.2.0",
- "@angular/router": "~3.1.0",
- "@angular/upgrade": "~2.2.0",
- "angular-in-memory-web-api": "~0.1.5",
- "bootstrap": "^3.3.7",
- "core-js": "^2.4.1",
- "reflect-metadata": "^0.1.8",
- "rxjs": "5.0.0-beta.12",
- "systemjs": "0.19.39",
- "zone.js": "^0.6.25"
- },
- "devDependencies": {
- "concurrently": "^3.0.0",
- "lite-server": "^2.2.2",
- "typescript": "^2.0.3",
- "typings": "^1.4.0"
- }
- }
app.dynamic.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 { HttpModule } from '@angular/http';
- import { RouterModule } from '@angular/router';
-
- import { routing, appRoutingProviders } from './route_config/dynamic/app.routes';
- import { HomeComponent } from './route_config/dynamic/app.component.home';
- import { HomePageComponent } from './route_config/dynamic/app.component.homepage';
- import { MenuTreeComponent } from './route_config/dynamic/app.component.menu';
-
- import { HelloWorldComponent } from './samplecode/01_helloworld/helloworld.component';
- import { FirstProgComponent } from './samplecode/01_helloworld/app.component.firstprog';
- import { TemplateComponent } from './samplecode/01_helloworld/app.component.template';
-
- @NgModule({
- imports: [BrowserModule, FormsModule, HttpModule, routing],
- declarations: [HomePageComponent, HomeComponent, MenuTreeComponent, HelloWorldComponent, FirstProgComponent, TemplateComponent],
- bootstrap: [HomePageComponent],
- schemas: [NO_ERRORS_SCHEMA],
- providers: [appRoutingProviders],
- })
-
- export class DynamicRouteModule { }
index.html
- <!DOCTYPE html>
- <html>
- <head>
- <title></title>
- <meta charset="utf-8" />
- <script src="resource/js/jquery.js"></script>
- <script type="text/javascript" charset="utf-8">
- function loadJson() {
- $(document).ready(function () {
- $.getJSON('route_config/dynamic/data/route_menu.json', function (json) {
- var data = [];
- for (var i = 0; i < json.length; i++) {
- if (json[i].isChildItem) {
- for (j = 0; j < json[i].childItem.length; j++) {
- data.push({
- key: json[i].childItem[j].key,
- routeKey: '#' + json[i].childItem[j].routeKey,
- path: '#' + json[i].childItem[j].routeKey,
- component: json[i].childItem[j].componentName
- })
- }
- }
- }
- sessionStorage.setItem("routeData", JSON.stringify(data));
- window.top.location.href = 'app.dynamic.module.html';
- });
- });
- }
- </script>
- </head>
- <body onload="loadJson();">
- Angular 2 Home Page
- </body>
- </html>
app.dynamic.module.html
- <!DOCTYPE html>
- <html lang="en">
- <head>
-
- <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">
- <link rel="shortcut icon" href="img/favicon/favicon.ico">
- </head>
- <body>
- <div class="content">
- <home-page></home-page>
- </div>
- <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>
-
-
- <script>document.write('<base href="' + document.location + '" />');</script>
- </body>
- </html>
main.ts
- import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
- import { DynamicRouteModule } from './app.dynamic.module';
-
- platformBrowserDynamic().bootstrapModule(DynamicRouteModule);
route_data.json
- [
- {
- "key": "item_01",
- "caption": "Basic Program",
- "displayOrder": 1,
- "isChildItem": true,
- "childItem": [
- {
- "key": "subitem_01",
- "caption": "Hello World",
- "displayOrder": 1,
- "componentName": "HelloWorldComponent",
- "routeKey": "/item_01_01"
- },
- {
- "key": "subitem_02",
- "caption": "First Program",
- "displayOrder": 2,
- "componentName": "FirstProgComponent",
- "routeKey": "/item_02_02"
- }
- ]
- },
- {
- "caption": "Nested Component",
- "displayOrder": 2,
- "isChildItem": false,
- "childItem": [
- {
- "caption": "Child Nested 1",
- "displayOrder": 1
- },
- {
- "caption": "Child Nested 2",
- "displayOrder": 2
- }
- ]
- },
- {
- "caption": "Data Binding",
- "displayOrder": 3,
- "isChildItem": false
- }
- ]
app.routes.ts
- import { Routes, RouterModule } from '@angular/router';
- import { HomeComponent } from './app.component.home';
- import { HelloWorldComponent } from '../../samplecode/01_helloworld/helloworld.component';
- import { FirstProgComponent } from '../../samplecode/01_helloworld/app.component.firstprog';
- import { TemplateComponent } from '../../samplecode/01_helloworld/app.component.template';
-
-
- export const routes: Routes = [
- { path: '', redirectTo: 'home', pathMatch: 'full' },
- { path: 'home', component: HomeComponent },
- { path: 'item_01_01', component: HelloWorldComponent },
- { path: 'item_02_02', component: FirstProgComponent },
- { path: 'template', component: TemplateComponent }
-
- ];
-
- export const appRoutingProviders: any[] = [
-
- ];
-
- export const routing = RouterModule.forRoot(routes);
Now, we need to create some sample components like HomeComponet, HelloWorldComponent, FirstComponent, and Template Component which will be loaded by lazy loading concept in the run time.
Please find the attached screenshots.
For sample code, please find the attached project.