Home  >  Angular 2

Angular 2/4 Child Routes and Relative Navigation Example

By Arvind Rai, June 17, 2017
This page will walk through Angular child routes and relative navigation example. A route can have one or more than one child routes. Child routes can have their own child routes and so on. A route is created using Angular Route interface and array of Route is Routes type. Route has different properties to handle route such as path, component, outlet, children, loadChildren etc. To create child route for a route, we need to use children property. To load child module in application module, we need to use loadChildren property. The component corresponding to a child route will open in router outlet of a component related to immediate parent route of the given child route. Child can have path parameters and also it can have empty path. Router supports relative path using ActivatedRoute. When we navigate to a route using Router.navigate() method then we need to pass instance of ActivatedRoute using relativeTo property. When we navigate to a route using RouterLink directive, we need not to pass instance of ActivatedRoute because RouterLink automatically supports ActivatedRoute.
In our example we will create two features, country feature and person feature. Both features will have its own folder, feature module and feature routing module that will follow "Separation of Concerns principle" recommended by Angular. Now we will discuss complete example step by step.

Technologies Used

Find the technologies being used in our example.
1. Angular 4.0.0
2. TypeScript 2.2.0
3. Node.js 6.10.1
4. Angular CLI 1.0.4
5. Angular Compiler CLI 4.0.0

Understanding Child Routes

Suppose base URL is "/" configured by <base href="/"> in index.html. We will create a diagram that will display the child routes for a component. The components shown in diagram will be used in our demo application.
Angular 2/4 Child Routes and Relative Navigation Example
Find the child routes corresponding to the components.
1. URL: /
Components: AppComponent

2. URL: /country
Components: AppComponent -> CountryComponent

3. URL: /country/add
Components: AppComponent -> CountryComponent -> AddCountryComponent

4. URL: /country/list
Components: AppComponent -> CountryComponent -> CountryListComponent

5. URL: /country/list/view/1
Components: AppComponent -> CountryComponent -> CountryListComponent -> CountryDetailComponent

6. URL: /country/list/edit/1
Components: AppComponent -> CountryComponent -> CountryListComponent -> CountryEditComponent

7. URL: /person
Component: AppComponent -> PersonComponent -> PersonListComponent

8. URL: /person/1
Component: AppComponent -> PersonComponent -> PersonListComponent -> PersonEditComponent

9. URL: /address
Component: AppComponent -> AddressComponent

Child Router Outlet

Find the diagram that shows child router outlet. We are using all components of our example in the diagram and by arrow we are showing which component will open in which component's <router-outlet>.
Angular 2/4 Child Routes and Relative Navigation Example
A component related to a child route is opened in <router-outlet> of a component related to immediate parent route. For example find the following components with their child routes.
1. Component: CountryComponent, URL: /country
2. Component: CountryListComponent, URL: /country/list
3. Component: CountryDetailComponent, URL: /country/list/view/1

We observe that path of CountryListComponent is the immediate child route of CountryComponent and hence CountryListComponent will open in the <router-outlet> of CountryComponent. In the same way the path of CountryDetailComponent is the immediate child route of CountryListComponent and hence CountryDetailComponent will open in the <router-outlet> of CountryListComponent.

Properties of Angular Routes Array

Routes is an array of Angular Route interface. Route is used to define a path. Find the properties of Route interface.
path: Defines path for a component.
component: Name of the component.
outlet: Name of the outlet component should be placed into.
data: Additional data provided to component via ActivatedRoute.
children: Array of child route definitions.
loadChildren: Reference to lazy loaded child routes.
redirectTo: Defines a URL to redirect current matched URL.

Find the sample examples.
1. Simple configuration with children property.
const countryRoutes: Routes = [
    { 
	 path: 'country',
         component: CountryComponent,
         children: [ 
	    {
		path: 'add',
		component: AddCountryComponent
	    }
         ]
    }
] 
2. Using redirectTo property.
[{ 
    path: 'country',
    component: CountryComponent,
    children: [ 
      {
	path: 'add',
	component: AddCountryComponent
      },
      {
	path: 'item/create',
	redirectTo: 'add'
      }
    ]
}] 

Child Routes Module

While creating our angular applications, we should follow angular recommended pattern as given below.
1. Each feature area should reside in its own folder.
2. Each feature should have its own feature module as well as feature routing module.
3. Each area should have its own area root component.
4. Each area root component should have its own router outlet and child routes.

Suppose we have two basic features in our demo application such as country and person, then we should use following folder structure and modules.
angular-demo
|
|--src
|   |
|   |--app 
|   |   |
|   |   |--country
|   |   |    | 
|   |   |    |--........
|   |   |    |--country-routing.module.ts (CountryRoutingModule) 
|   |   |    |--country.module.ts (CountryModule)
|   |   |
|   |   |--person
|   |   |    | 
|   |   |    |--........
|   |   |    |--person-routing.module.ts (PersonRoutingModule)
|   |   |    |--person.module.ts (PersonModule)
|   |   |
|   |   |--........
|   |   |--app-routing.module.ts (AppRoutingModule)
|   |   |--app.module.ts (AppModule) 
CountryRoutingModule will be configured in CountryModule and PersonRoutingModule will be configured in PersonModule. Both child modules i.e. CountryModule and PersonModule will be configured in AppModule. To load child routing modules, their child modules will be loaded by AppRoutingModule by calling loadChildren. Find the code snippet of AppRoutingModule in our demo application.
app-routing.module.ts
const routes: Routes = [
   {
      path: 'country',
      loadChildren: 'app/country/country.module#CountryModule',
      data: { preload: true }
   },
   {
      path: 'person',
      loadChildren: 'app/person/person.module#PersonModule',
      data: { preload: true }
   }
]; 
@NgModule will import above routes as follows.
RouterModule.forRoot(routes) 
@NgModule will export RouterModule.

Creating and Configuring Child Routes

Child routes are created using children property of Angular Route interface. Child routes are configured using forChild() method of RouterModule. Suppose we have country feature. Now find the routing module for this feature.
const countryRoutes: Routes = [
	{ 
	  path: 'country',
          component: CountryComponent,
          children: [ 
	    {
	       path: 'add',
	       component: AddCountryComponent
	    },
	    {
	       path: 'list',
	       component: CountryListComponent,
	       children: [
		   {
		       path: 'view/:country-id',
		       component: CountryDetailComponent
		   },
		   {
		       path: 'edit/:country-id',
		       component: CountryEditComponent
		   },			   
		]
	     }	
	   ]
	}  
];

@NgModule({
  imports: [ RouterModule.forChild(countryRoutes) ],
  exports: [ RouterModule ]
})
export class CountryRoutingModule{ } 
Find the route description.
1. URL: /country
Components: AppComponent -> CountryComponent

2. URL: /country/add
Components: AppComponent -> CountryComponent -> AddCountryComponent

3. URL: /country/list
Components: AppComponent -> CountryComponent -> CountryListComponent

4. URL: /country/list/view/1
Components: AppComponent -> CountryComponent -> CountryListComponent -> CountryDetailComponent

5. URL: /country/list/edit/1
Components: AppComponent -> CountryComponent -> CountryListComponent -> CountryEditComponent

Child Routes with Parameters

To create routes with path parameter, define the path as given below.
const countryRoutes: Routes = [
	{ 
	  path: 'country',
          component: CountryComponent,
          children: [ 
	    {
	       path: 'list',
	       component: CountryListComponent,
	       children: [
		   {
		       path: 'view/:country-id',
		       component: CountryDetailComponent
		   }
		]
	     }	
	   ]
	}  
]; 
The CountryDetailComponent will open for a country id. country-id is a path variable that will accept country id. Find the URL for country id 101.
/country/list/view/101 
This URL will be accepted by following path.
{
       path: 'view/:country-id',
       component: CountryDetailComponent
}

Empty Child Routes

A route can be empty. If we want to open a component by default then we can leave route empty. Find the example.
const personRoutes: Routes = [
   { 
	  path: 'person',
          component: PersonComponent,
	  children: [ 
	    {
		 path: '',
		 component: PersonListComponent,
		 children: [
		   {
		      path: ':id',
		      component: PersonEditComponent
		   }
		 ]			
	    }
	 ]
   }  
]; 
The path for PersonListComponent is empty. So the path for PersonListComponent will be calculated as given below. /person + '' = /person
Find the description of routes now.
1. URL: /person
Components: AppComponent -> PersonComponent -> PersonListComponent
2. URL: /person/1
Components: AppComponent -> PersonComponent -> PersonEditComponent Angular router supports relative navigation. For route name lookup, we use directory-like syntax in our path.
./ or no leading slash is relative to current level.
../ is used to go up one level in path.

Now we will understand relative navigation using Router.navigate() method and RouterLink directive.

1. Using Router.navigate() method

To support relative navigation to Router.navigate(), we need to pass ActivatedRoute using which router comes to know where it is in current route tree. To pass ActivatedRoute we need to use relativeTo property. To get the instance of ActivatedRoute and Router use the constructor.
constructor(
	private countryService: CountryService,
	private route: ActivatedRoute,
        private router: Router) { } 
Now suppose a component has following source and target route.
Source route from where the component has opened: /country/add
Target route to navigate: /country/list/view/101

Now Router.navigate() will be used as follows.
goToView(country:Country) {
     this.router.navigate([ '../list/view', country.countryId ], { relativeTo: this.route });
}
If we want to use absolute path, then write the full path.
this.router.navigate(['/country/list/view', country.countryId]); 
Disadvantage of absolute path is that if the path /country is changed then we need to edit our component code to change the path, too.

2. Using RouterLink Directive

RouterLink directive has support of ActivatedRoute automatically for relative navigation. We can use relative path and absolute path both with RouterLink directive.
Now suppose a component has following source and target route.
Source route from where the component has opened: /country/add
Target route to navigate: /country/list/view/101
Using relative path:
<a [routerLink]="['../list/view', country.countryId]" routerLinkActive="active">View</a>
Using absolute path:
<a [routerLink]="['/country/list/view', country.countryId]" routerLinkActive="active">View</a>

Complete Example

In our example we have two main features. Every feature resides in its own folder with its associated files. We will provide code feature wise.

1. Project Structure

Find the project structure of our demo application.
angular-demo
|
|--src
|   |
|   |--app 
|   |   |
|   |   |--country
|   |   |    | 
|   |   |    |--country.component.ts
|   |   |    |--country.ts
|   |   |    |--country.module.ts
|   |   |    |--country-routing.module.ts
|   |   |    |
|   |   |    |--add-country
|   |   |    |    |  
|   |   |    |    |--add-country.component.html
|   |   |    |    |--add-country.component.ts
|   |   |    |    |
|   |   |    |--country-list
|   |   |    |    |
|   |   |    |    |--country.list.component.html
|   |   |    |    |--country.list.component.ts
|   |   |    |    |
|   |   |    |    |--detail
|   |   |    |    |   |
|   |   |    |    |   |--country.detail.component.html
|   |   |    |    |   |--country.detail.component.ts
|   |   |    |    |
|   |   |    |    |--edit
|   |   |    |    |   |
|   |   |    |    |   |--country.edit.component.html
|   |   |    |    |   |--country.edit.component.ts
|   |   |    |    |
|   |   |    |    |
|   |   |    |--service
|   |   |    |    |
|   |   |    |    |--country.service.ts
|   |   |
|   |   |--person
|   |   |    | 
|   |   |    |--person.component.ts
|   |   |    |--person.ts
|   |   |    |--person-routing.module.ts
|   |   |    |--person.module.ts
|   |   |    | 
|   |   |    |--person-list 
|   |   |    |    |
|   |   |    |    |--person.list.component.html 
|   |   |    |    |--person.list.component.ts
|   |   |    |    |
|   |   |    |    |--edit
|   |   |    |    |   |
|   |   |    |    |   |--person.edit.component.html
|   |   |    |    |   |--person.edit.component.ts
|   |   |    | 
|   |   |    |--service
|   |   |    |    |  
|   |   |    |    |--person.service.ts
|   |   |
|   |   |--address.component.ts
|   |   |--page-not-found.component.ts
|   |   |--app.component.ts
|   |   |--app-routing.module.ts
|   |   |--app.module.ts
|   |   
|   |--main.ts
|   |--index.html
|   |--styles.css
|
|--node_modules
|--package.json

2. Feature One Complete Code of Demo Application

Here we will provide complete code of country feature.
add-country.component.html
<h3>Add Country</h3>
<form [formGroup]="countryForm" (ngSubmit)="onFormSubmit()">
   <p> Name: <input formControlName="name"> </p>
   <p> Capital: <input formControlName="capital"> </p>
   <p> Currency: <input formControlName="currency"> </p>
   <p> <button>Add</button> </p>
</form> 
add-country.component.ts
import { Component } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';

import { CountryService } from '../service/country.service';
import { Country } from '../country';
@Component({
    templateUrl: './add-country.component.html'
})
export class AddCountryComponent { 
	constructor(
		private countryService: CountryService,
		private route: ActivatedRoute,
                private router: Router) { }
		
	countryForm = new FormGroup({
	   id: new FormControl(),
	   name: new FormControl(),
	   capital: new FormControl(),
	   currency: new FormControl()
	});	
	onFormSubmit() {
	   let name = this.countryForm.get('name').value;
	   let capital = this.countryForm.get('capital').value;
	   let currency = this.countryForm.get('currency').value;
	   
	   let country = new Country(null, name, capital, currency);
	   this.countryService.addCountry(country)
	      .then(data =>
    		  this.router.navigate([ '../list/view', data.countryId ], { relativeTo: this.route })
           );
	}
} 
country.detail.component.html
<h3>Country Detail </h3>
<div *ngIf="country">
<p><b>Id:</b> {{country.countryId}},  
<b>Name:</b> {{country.countryName}} </p>
<p><b>Capital:</b> {{country.capital}},
<b>Currency:</b> {{country.currency}}</p>
</div> 
country.detail.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import 'rxjs/add/operator/switchMap';

import { CountryService } from '../../service/country.service';
import { Country } from '../../country';

@Component({
  templateUrl: './country.detail.component.html' 
}) 
export class CountryDetailComponent implements OnInit { 
    country: Country;
    constructor(
	        private countryService: CountryService,
		private route: ActivatedRoute) { }
    ngOnInit() {
       this.route.params
        .switchMap((params: Params) => this.countryService.getCountry(+params['country-id']))
        .subscribe(country => this.country = country);
    }					
} 
country.edit.component.html
<h3>Edit Country</h3>
<p *ngIf="country"><b>Country Id: {{country.countryId }} </b></p>
<form [formGroup]="countryForm" (ngSubmit)="onFormSubmit()">
   <p> Name: <input formControlName="name"> </p>
   <p> Capital: <input formControlName="capital"> </p>
   <p> Currency: <input formControlName="currency"> </p>
   <p> <button>Update</button> </p>
</form>  
country.edit.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router, Params } from '@angular/router';
import { FormControl, FormGroup } from '@angular/forms';
import 'rxjs/add/operator/switchMap';

import { CountryService } from '../../service/country.service';
import { Country } from '../../country';

@Component({
  templateUrl: './country.edit.component.html' 
}) 
export class CountryEditComponent implements OnInit { 
    country: Country;
    constructor(
		private countryService: CountryService,
		private route: ActivatedRoute,
                private router: Router) { }
		
    ngOnInit() {
       this.route.params
        .switchMap((params: Params) => this.countryService.getCountry(+params['country-id']))
         .subscribe(country => {
		       this.country = country;
		       this.setFormValues();
		}
	 );
    }	
    countryForm = new FormGroup({
	 name: new FormControl(),
	 capital: new FormControl(),
	 currency: new FormControl()
    });	
    setFormValues() {
	 this.countryForm.setValue({name: this.country.countryName, 
	      capital: this.country.capital, currency: this.country.currency});
    }	
    onFormSubmit() {
	this.country.countryName = this.countryForm.get('name').value;
	this.country.capital = this.countryForm.get('capital').value;
	this.country.currency = this.countryForm.get('currency').value;
	   
	this.countryService.updateCountry(this.country)
	     .then(() =>
    		  this.router.navigate([ '../../' ], { relativeTo: this.route })
		 );
	}
} 
country.list.component.html
<h3>Country List</h3>
<div *ngFor="let country of countries | async" [ngClass]= "'sub-child-menu'">
 <p>{{country.countryId}}. {{country.countryName}}
	<a [routerLink]="['view', country.countryId]" routerLinkActive="active">View</a> |
	<a [routerLink]="['edit', country.countryId]" routerLinkActive="active">Edit</a>
 </p>
</div>
<div [ngClass]= "'sub-child-container'">
	<router-outlet></router-outlet>  
</div> 
country.list.component.ts
import { Component, OnInit } from '@angular/core';

import { CountryService } from '../service/country.service';
import { Country } from '../country';

@Component({
  templateUrl: './country.list.component.html' 
}) 
export class CountryListComponent implements OnInit { 
  countries: Promise<Country[]>
  constructor(private countryService: CountryService) {}
  ngOnInit() {
    this.countries = this.countryService.getCountries();
  }	
} 
country.service.ts
import { Injectable } from '@angular/core';

import { Country } from '../country';

const COUNTRIES = [
  new Country(1, 'India', 'New Delhi', 'INR'),
  new Country(2, 'China', 'Beijing', 'RMB')
];
let countriesPromise = Promise.resolve(COUNTRIES);

@Injectable()
export class CountryService { 
     getCountries(): Promise<Country[]> {
	    return countriesPromise;
     }
     getCountry(id: number): Promise<Country> {
        return this.getCountries()
            .then(countries => countries.find(country => country.countryId === id));
     }	
     updateCountry(country: Country): Promise<Country> {
	 return this.getCountries()
	  .then(countries => {
	        let countryObj = countries.find(ob => ob.countryId === country.countryId);
                countryObj = country;
		return countryObj;
	     }
	  );
     }	
     addCountry(country: Country): Promise<Country> {
	return this.getCountries()
	  .then(countries => {
	      let maxIndex = countries.length - 1;
	      let countryWithMaxIndex = countries[maxIndex];
	      country.countryId = countryWithMaxIndex.countryId + 1;
	      countries.push(country);
	      return country;
	    }
	  );
     }	
} 
country.ts
export class Country { 
	constructor(public countryId:number, public countryName:string,
            	public capital:string, public currency:string) {
	}
} 
country.component.ts
import { Component } from '@angular/core';
@Component({
  template: `<h2>Welcome to Country Home</h2>
   <nav [ngClass] = "'child-menu'">
      <ul>
	<li><a [routerLink]="['add']" routerLinkActive="active">Add Country</a></li>
	<li><a [routerLink]="['list']" routerLinkActive="active">Country List</a></li>
      </ul>  
   </nav>  
   <div [ngClass] = "'child-container'">	
	  <router-outlet></router-outlet>	
   </div>
  `
})
export class CountryComponent { 
} 
country-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { CountryComponent }  from './country.component';
import { CountryListComponent }  from './country-list/country.list.component';
import { AddCountryComponent }  from './add-country/add-country.component';
import { CountryDetailComponent }  from './country-list/detail/country.detail.component';
import { CountryEditComponent }  from './country-list/edit/country.edit.component';

const countryRoutes: Routes = [
	{ 
	  path: 'country',
          component: CountryComponent,
          children: [ 
	    {
		   path: 'add',
		   component: AddCountryComponent
	    },
	    {
	           path: 'list',
		   component: CountryListComponent,
		   children: [
		       {
			   path: 'view/:country-id',
		           component: CountryDetailComponent
		       },
		       {
			   path: 'edit/:country-id',
		           component: CountryEditComponent
		       },			   
		   ]
	    }	
	  ]
	}  
];

@NgModule({
  imports: [ RouterModule.forChild(countryRoutes) ],
  exports: [ RouterModule ]
})
export class CountryRoutingModule{ } 
country.module.ts
import { NgModule }   from '@angular/core';
import { CommonModule }   from '@angular/common';
import { ReactiveFormsModule }    from '@angular/forms';

import { CountryComponent }  from './country.component';
import { AddCountryComponent }  from './add-country/add-country.component';
import { CountryListComponent }  from './country-list/country.list.component';
import { CountryDetailComponent }  from './country-list/detail/country.detail.component';
import { CountryEditComponent }  from './country-list/edit/country.edit.component';
import { CountryService } from './service/country.service';
import { CountryRoutingModule }  from './country-routing.module';

@NgModule({
  imports: [     
        CommonModule,
	ReactiveFormsModule,
	CountryRoutingModule
  ], 
  declarations: [
	CountryComponent,
	AddCountryComponent,
	CountryListComponent,
	CountryEditComponent,
	CountryDetailComponent
  ],
  providers: [ CountryService ]
})
export class CountryModule { } 
CommonModule includes all the basic Angular directives such as NgIf, NgFor, NgClass etc. Now find the print screen of feature one output.
Angular 2/4 Child Routes and Relative Navigation Example

3. Feature Two Complete Code of Demo Application

Here we will provide complete code of person feature.
person.edit.component.html
<h3>Edit Person</h3>
<p *ngIf="person"><b>Person Id: {{person.personId }} </b></p>
<form [formGroup]="personForm" (ngSubmit)="onFormSubmit()">
   <p> Name: <input formControlName="name"> </p>
   <p> City: <input formControlName="city"> </p>
   <p> <button>Update</button> </p>
</form> 
person.edit.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router, Params } from '@angular/router';
import { FormControl, FormGroup } from '@angular/forms';
import 'rxjs/add/operator/switchMap';

import { PersonService } from '../../service/person.service';
import { Person } from '../../person';

@Component({
  templateUrl: './person.edit.component.html' 
}) 
export class PersonEditComponent implements OnInit { 
        person: Person;
	constructor(
		private personService: PersonService,
		private route: ActivatedRoute,
                private router: Router) { }
		
        ngOnInit() {
          this.route.params
            .switchMap((params: Params) => this.personService.getPerson(+params['id']))
            .subscribe(person => {
		            this.person = person;
			    this.setFormValues();
			}
	    );
        }	
	personForm = new FormGroup({
	   name: new FormControl(),
	   city: new FormControl()
	});	
	setFormValues() {
	   this.personForm.setValue({name: this.person.name, city: this.person.city});
	}	
	onFormSubmit() {
	   this.person.name = this.personForm.get('name').value;
	   this.person.city = this.personForm.get('city').value;
	   
	   this.personService.updatePerson(this.person)
	     .then(() =>
    		  this.router.navigate([ '../' ], { relativeTo: this.route })
		 );
	}
} 
person.list.component.html
<h3>Person List</h3>
<div *ngFor="let person of persons | async" [ngClass]= "'sub-child-menu'">
<p>{{person.personId}}. {{person.name}}, {{person.city}}
   <button type="button" (click)="goToEdit(person)">Edit</button>
</p>
</div>
<div [ngClass]= "'sub-child-container'">
	<router-outlet></router-outlet>  
</div>  
person.list.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';

import { PersonService } from '../service/person.service';
import { Person } from '../person';

@Component({
  templateUrl: './person.list.component.html' 
}) 
export class PersonListComponent implements OnInit { 
  persons: Promise<Person[]>
  constructor(		
        private personService: PersonService,
        private route: ActivatedRoute,
        private router: Router) {}
  ngOnInit() {
      this.persons = this.personService.getPersons();
  }	
  goToEdit(person:Person) {
      this.router.navigate([ person.personId ], { relativeTo: this.route });
  }
} 
person.service.ts
import { Injectable } from '@angular/core';

import { Person } from '../person';

const PERSONS = [
  new Person(1, 'Mahesh', 'Varanasi'),
  new Person(2, 'Ram', 'Ayodhya'),  
  new Person(3, 'Kishna', 'Mathura')
];
let personsPromise = Promise.resolve(PERSONS);

@Injectable()
export class PersonService { 
	getPersons(): Promise<Person[]> {
	    return personsPromise;
	}
	getPerson(id: number): Promise<Person> {
           return this.getPersons()
            .then(persons => persons.find(person => person.personId === id));
        }	
        updatePerson(person: Person): Promise<Person> {
	    return this.getPersons()
		  .then(persons => {
		        let personObj = persons.find(ob => ob.personId === person.personId);
                        personObj = person;
			return personObj;
		     }
		  );
        }	
} 
person.ts
export class Person { 
	constructor(public personId:number, public name:string, public city:string) {
	}
} 
person.component.ts
import { Component } from '@angular/core';
@Component({
  template: `<h2>Welcome to Person Home</h2>
	     <div [ngClass] = "'child-container'">	
	        <router-outlet></router-outlet>	
	     </div>
  `
})
export class PersonComponent { 
} 
person-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { PersonComponent }  from './person.component';
import { PersonListComponent }  from './person-list/person.list.component';
import { PersonEditComponent }  from './person-list/edit/person.edit.component';

const personRoutes: Routes = [
	{ 
	  path: 'person',
          component: PersonComponent,
	  children: [ 
	    {
		path: '',
		component: PersonListComponent,
		children: [
		   {
		     path: ':id',
		     component: PersonEditComponent
		   }
		]			
	    }
	  ]
	}  
];

@NgModule({
  imports: [ RouterModule.forChild(personRoutes) ],
  exports: [ RouterModule ]
})
export class PersonRoutingModule{ } 
person.module.ts
import { NgModule }   from '@angular/core';
import { CommonModule }   from '@angular/common';
import { ReactiveFormsModule }    from '@angular/forms';

import { PersonComponent }  from './person.component';
import { PersonListComponent }  from './person-list/person.list.component';
import { PersonEditComponent }  from './person-list/edit/person.edit.component';
import { PersonService } from './service/person.service';
import { PersonRoutingModule }  from './person-routing.module';

@NgModule({
  imports: [     
        CommonModule,
	ReactiveFormsModule,
	PersonRoutingModule
  ], 
  declarations: [
	PersonComponent,
	PersonListComponent,
	PersonEditComponent
  ],
  providers: [ PersonService ]
})
export class PersonModule { } 
Find the print screen of feature two output.
Angular 2/4 Child Routes and Relative Navigation Example

4. Application Module and Other Components

Find application module and other components.
address.component.ts
import { Component } from '@angular/core';
@Component({
  template: `
      <h3>ADDRESS</h3>
          <p><b> Article: Child routing & Relative navigation </b></p>
	  <p><b> Category: Angular </b></p>
	  <p><b> Website: CONCRETEPAGE.COM </b></p>
     <div>
         <a [routerLink]="['/location']">Find Location</a>
     </div> 
  `
})
export class AddressComponent { 
} 
page-not-found.component.ts
import { Component } from '@angular/core';
import { Location } from '@angular/common';

@Component({
  template: `<h2>Page Not Found.</h2>
             <div>
                <button (click)="goBack()">Go Back</button>
	     </div>
            `
})
export class PageNotFoundComponent {
	constructor(private location: Location) { }
	goBack(): void {
           this.location.back();
        }
} 
app.component.ts
import { Component } from '@angular/core';
@Component({
  selector: 'app-root',
  template: `
	<nav [ngClass] = "'parent-menu'">
	  <ul>
		 <li><a routerLink="/country" routerLinkActive="active">Country</a></li>
		 <li><a routerLink="/person" routerLinkActive="active">Person</a></li>
		 <li><a routerLink="/address" routerLinkActive="active">Address</a></li>
	  </ul> 
	</nav>  
	<div [ngClass] = "'parent-container'">	
	  <router-outlet></router-outlet>	
	</div>
  `
})
export class AppComponent { 
} 
app-routing.module.ts
import { NgModule }      from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { AddressComponent }  from './address.component';
import { PageNotFoundComponent }  from './page-not-found.component';

const routes: Routes = [
	{
	   path: 'country',
           loadChildren: 'app/country/country.module#CountryModule',
           data: { preload: true }
	},
	{
	   path: 'person',
           loadChildren: 'app/person/person.module#PersonModule'
	},
	{
	   path: 'address',
	   component: AddressComponent
	},	
	{
	   path: '',
	   redirectTo: '/country',
	   pathMatch: 'full'
	},
        {
	   path: '**',
	   component: PageNotFoundComponent 
        }	
];
@NgModule({
  imports: [ 
          RouterModule.forRoot(routes) 
  ],
  exports: [ 
          RouterModule 
  ]
})
export class AppRoutingModule{ }  
app.module.ts
import { NgModule }   from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent }  from './app.component';
import { AddressComponent }  from './address.component';
import { PageNotFoundComponent }  from './page-not-found.component';

import { CountryModule }  from './country/country.module';
import { PersonModule }  from './person/person.module';
import { AppRoutingModule }  from './app-routing.module';

@NgModule({
  imports: [     
        BrowserModule,
	CountryModule,
	PersonModule,
	AppRoutingModule,
  ],
  declarations: [
        AppComponent,
	AddressComponent,
	PageNotFoundComponent
  ],
  providers: [ ],
  bootstrap: [ AppComponent ]
})
export class AppModule { } 
index.html
<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>Angular Demo</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <app-root>Loading...</app-root>
</body>
</html> 
styles.css
.parent-menu ul {
    list-style-type: none;
    margin: 0;
    padding: 0;
    overflow: hidden;
    background-color: #333;
}
.parent-menu li {
    float: left;
}
.parent-menu li a {
    display: block;
    color: white;
    text-align: center;
    padding: 15px 15px;
    text-decoration: none;
}
.parent-menu li a:hover:not(.active) {
    background-color: #111;
}
.parent-menu .active{
    background-color: #4CAF50;
}
.parent-container {
    padding-left: 10px;
}
.child-container {
    padding-left: 10px;
}
.sub-child-container {
    padding-left: 10px;
}
.child-menu  {
    padding-left: 25px;
}
.child-menu .active{
    color: #4CAF50;
}
.sub-child-menu {
    background-color: #f1f1f1;  
    width: 275px;
    list-style-type: none;	
    margin: 0;
    padding: 0;
}
.sub-child-menu .active{
    color: #4CAF50;
}
button {
    background-color: #008CBA;
    color: white;
} 

Run Application

To run the application, find following steps.
1. Download source code using download link given on this page.
2. In your angular CLI application, replace src folder from the downloaded one.
3. Run ng serve using command prompt.
4. Now access the URL http://localhost:4200

I am done now. Happing Angular 2+ learning!

References

Routing & Navigation
Angular 2 Routing and Navigation Example

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
FIND MORE TUTORILAS





Copyright ©2017 concretepage.com, all rights reserved |Privacy Policy | Contact Us