Nested Component In Angular

Introduction

 
In this article, we are going to create nested components and share data between them.
 
Highlights
  • Creating a nested component
  • Loading nested component in a container component 
  • Sharing data between container/Parent component to child component and vice-versa 
Problem Statement
 
Loading ArticlelistComponent in the root component when a user clicks on the View articles list button as shown below:
Demosteps
 
Create a component called articlelist using the following command,
 
ng generate component articlelist
 
Above command will create a folder with name articlelist with the following files,
  • articlelist.component.ts 
  • articlelist.component.html
  • articlelist.component.css
  • articlelist.component.spec.ts
ArticleListComponent class will be added in app.module.ts file
 
Write the below-given code in articlelist.component.ts
  1. import { Component, OnInit } from '@angular/core';    
  2.     
  3. @Component({    
  4.   selector: 'app-articlelist',    
  5.   templateUrl: './articlelist.component.html',    
  6.   styleUrls: ['./articlelist.component.css']    
  7. })    
  8. export class ArticlelistComponent implements OnInit {    
  9.   articles = [    
  10.     { articleId: 1, articleName: 'Getting started with Angular' },    
  11.     { articleId: 2, articleName: 'Templates in Angular' },    
  12.     { articleId: 3, articleName: 'Builtin Pipes in Angular' },    
  13.        
  14.   ];    
  15.   constructor() { }    
  16.     
  17.   ngOnInit(): void {    
  18.   }    
  19. }    
Write the below-given code in articlelist.component.html 
  1. <table border="1">    
  2.     <thead>    
  3.       <tr>    
  4.         <th>article ID</th>    
  5.         <th>article Name</th>    
  6.       </tr>    
  7.     </thead>    
  8.     <tbody>    
  9.       <tr *ngFor="let article of articles">    
  10.         <td>{{article.articleId}}</td>    
  11.         <td>{{article.articleName}}</td>    
  12.       </tr>    
  13.     </tbody>    
  14.   </table>  
Add the following code in articlelist.component.css 
  1. tr{    
  2.     text-align:center;    
  3. }    
Write the below-given code in app.component.html
  1. <router-outlet>    
  2.   <h2> Popular articles </h2>    
  3.   <button (click)="show=true">View article list</button><br/><br/>    
  4.   <div *ngIf="show">    
  5.       <app-articlelist></app-articlelist>    
  6.   </div>    
  7. </router-outlet>  
Write the below-given code in app.component.ts
  1. import { Component } from '@angular/core';    
  2.     
  3.  @Component({    
  4.   selector: 'app-root',    
  5.   templateUrl: './app.component.html',    
  6.   styleUrls: ['./app.component.css']    
  7. })    
  8. export class AppComponent {    
  9.   show:boolean;    
  10. }   
Save the files and check the output in the browser.
 
Now we are going to see how to pass data from container/Parent component to child component.
 
To achieve this we can use @Input decorator in the child component on any property type like arrays, objects, etc. 
 
Problem Statement
 
Let us create an AppComponent which displays a dropdown with a list of articles as values in it. Create another component called articleist component and load it in AppComponent which should display the article details. When a user selects a article from the dropdown, the corresponding article details should be loaded:
 
After selecting the particular article its details should be visible as below,
 
Now let's start the implementation,
 
Open article list.component.ts file used in the previous example and add input setter method for property cName in the component as shown below in Line 18:
  1. import { Component, OnInit, Input } from '@angular/core';    
  2.     
  3. @Component({    
  4.   selector: 'app-articlelist',    
  5.   templateUrl: './articlelist.component.html',    
  6.   styleUrls: ['./articlelist.component.css']    
  7. })    
  8. export class ArticlelistComponent implements OnInit {    
  9.   articles = [    
  10.     { articleId: 1, articleName: 'Getting started with Angular' },    
  11.     { articleId: 2, articleName: 'Templates in Angular' },    
  12.     { articleId: 3, articleName: 'Builtin Pipes in Angular' },    
  13.        
  14.   ];    
  15.     
  16.   article: any[];    
  17.   @Input() set cName(name: string) {    
  18.     this.article = [];    
  19.     for (let i = 0; i < this.articles.length; i++) {    
  20.       if (this.articles[i].articleName === name) {    
  21.         this.article.push(this.articles[i]);    
  22.       }    
  23.     }    
  24.   }    
  25.   constructor() { }    
  26.     
  27.   ngOnInit(): void {    
  28.   }    
  29.     
  30. }    
Open article list.component.html and add the following code 
  1. <table border="1">    
  2.     <thead>    
  3.       <tr>    
  4.         <th>article ID</th>    
  5.         <th>article Name</th>    
  6.       </tr>    
  7.     </thead>    
  8.     <tbody>    
  9.       <tr *ngFor="let c of article">    
  10.         <td>{{c.articleId}}</td>    
  11.         <td>{{c.articleName}}</td>    
  12.       </tr>    
  13.     </tbody>    
  14.   </table>    
Add the following in app.component.html
  1. <router-outlet>    
  2.    <h2> Popular articles </h2>    
  3. Select a article to view <select #article (change)="name = article.value">    
  4.     <option value="Getting started with Angular">Getting started with Angular</option>    
  5.     <option value="Templates in Angular">Templates in Angular</option>    
  6.     <option value="Builtin Pipes in Angular">Builtin Pipes in Angular</option>    
  7.     </select><br/><br/>    
  8.     <app-articlelist [cName]="name"></app-articlelist>>    
  9. </router-outlet>    
Add the following in app.component.ts
  1. import { Component } from '@angular/core';    
  2.     
  3.  @Component({    
  4.   selector: 'app-root',    
  5.   templateUrl: './app.component.html',    
  6.   styleUrls: ['./app.component.css']    
  7. })    
  8. export class AppComponent {    
  9.      
  10.   name:string;    
  11. }   
Now observe the output on the browser.
 
Now we are going to see how to pass data from child component to container/parent component,
 
To achieve this, if a child component wants to send data to its parent component, then it must create a property with @Output decorator. 
 
The only method for the child component to pass data to its parent component is through events. The property must be of type EventEmitter 
 
Problem Statement
 
Let us create an AppComponent which loads another component called articlelist component. Create another component called articleistComponent which should display the articles list in a table along with a register button in each row. When a user clicks on the register button, it should send that articleName value back to AppComponent where it should display registration successful message along with articleName.
 
Demosteps
 
Open articlelist.component.ts file created in the previous example and add the following code
  1. import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';    
  2.     
  3. @Component({    
  4.   selector: 'app-articlelist',    
  5.   templateUrl: './articlelist.component.html',    
  6.   styleUrls: ['./articlelist.component.css']    
  7. })    
  8. export class ArticlelistComponent  {    
  9.   @Output() OnRegister = new EventEmitter<string>();    
  10.   articles = [    
  11.     { articleId: 1, articleName: 'Getting started with Angular' },    
  12.     { articleId: 2, articleName: 'Templates in Angular' },    
  13.     { articleId: 3, articleName: 'Builtin Pipes in Angular' },    
  14.        
  15.   ];    
  16.   register(articleName: string) {    
  17.     this.OnRegister.emit(articleName);    
  18.   }    
  19. }    
Open articlelist.component.html and add the following code
  1. <table border="1">    
  2.     <thead>    
  3.       <tr>    
  4.         <th>article ID</th>    
  5.         <th>article Name</th>    
  6.       </tr>    
  7.     </thead>    
  8.     <tbody>    
  9.       <tr *ngFor="let article of articles">    
  10.         <td>{{article.articleId}}</td>    
  11.         <td>{{article.articleName}}</td>    
  12.         <td><button (click)="register(article.articleName)">Register</button></td>    
  13.       </tr>    
  14.     </tbody>    
  15.   </table>    
Add the following in app.component.html
  1. <router-outlet>    
  2. <h2> Popular articles</h2>    
  3. <app-articlelist (OnRegister)="articleReg($event)"></app-articlelist>    
  4. <br/><br/>    
  5. <div *ngIf="message">{{message}}</div>    
  6. </router-outlet>    
Add the following code in app.component.ts 
  1. import { Component } from '@angular/core';    
  2.     
  3.  @Component({    
  4.   selector: 'app-root',    
  5.   templateUrl: './app.component.html',    
  6.   styleUrls: ['./app.component.css']    
  7. })    
  8. export class AppComponent {    
  9.      
  10.   message: string;    
  11.   articleReg(articleName: string) {    
  12.     this.message = `Your registration for ${articleName} is successful`;    
  13.   }    
  14. }  
Now observe the output screen-
After clicking on Register button, you will view the below output screen on your browser,
 

Summary

 
In this article, we explored the nested component details and the concept of passing data from container/parent component to child component and vice-versa with examples.
 
Hope you like the article. Until next time - Happy Reading Cheers