In this post, we will learn about Container and Presentation components in Angular with a sample project.
Once the application is created, run the below command to make sure that it's created correctly.
To add modules and components run the below commands. we will create a "employee" module and component with the employeedetail child component.
- ng g m employee
- ng g c employee
- ng g c employee/employeedetail
Add Parent(Container) and child(presentation) component codes
We need to add below code in "employee.component.ts". We have added "employeeData" property and assigned a test data. (Line:02 and 05 to 08).
- export class EmployeeComponent implements OnInit {
- public employeeData: any;
- constructor() { }
- ngOnInit(): void {
- this.employeeData = {
- name : 'Test EmployeeName',
- email: '[email protected]'
- };
- console.log(this.employeeData.name);
- }
- }
In "employee.component.html", we need to add the "app-employee-detail" tag and "[employeedata]" property binding. The employee detail child component html content will be placed in this placeholder.
- <p>Employee</p>
- <app-employee-detail [employeeData]="employeeData"></app-employee-detail>
Add the below code in "employee-detail.component.ts". In Line 02 we added the "@Input" which will inject input property from Parent controller.
- export class EmployeeDetailComponent implements OnInit {
- @Input() public employeeData: any;
- constructor() { }
- ngOnInit(): void {
- console.log(this.employeeData.name);
- }
- }
Also add the below code in "" html file to display the values in UI.
- Name: {{employeeData.name}}
- <br/>
- Email: {{employeeData.email}}
Now run the application to see the output. Now, we have successfully passed the data from Parent to child component using "Input" properties.
Add Output Property
Now we will try to change data in the child component and pass it to the container component using the "Output" property.
Add the below output property in "employee-detail" component. Line 03 we have added "employeeChanged" output property. Also, I added the "employeeChange" event to change the employee name (Line 07 to 11).
- export class EmployeeDetailComponent implements OnInit {
- @Input() public employeeData: any;
- @Output() public employeeChanged = new EventEmitter<any>();
- constructor() { }
- ngOnInit(): void {
- }
- employeeChange(){
- console.log(this.employeeData.name);
- this.employeeData.name = 'Name Changed from EmployeeDetail';
- this.employeeChanged.emit(this.employeeData);
- }
- }
Add the below "button" control to "employee-detail.html" to trigger "employeeChange" event.
- <button (click)="employeeChange()">Update Employee</button>
To receive data in "Employee" component, add the below "employeeChanged" event to update state from child component.
- <app-employee-detail [employeeData]="employeeData" (employeeChanged)='changed($event)'></app-employee-detail>
Also implement the "changed" event in "employee" component cs file.
- changed(employeeData: any){
- this.employeeData = employeeData;
- }
Now run the application to test our changes and the initial employee data loaded.
Once we click the "Update Employee" button, "Employee Name" is changed as expected.
Add Change detection strategy
The strategy that the default change detector uses to detect changes is called "ChangeDetectionStrategy". By default, angular will use the "Default" strategy to all the child components.
"Presentation/Child component should not change the state/data", we can achieve this point using change detection strategy. Our child components have various user events, timer, promises. Angular will detect changes for all these events, we don't need to detect changes for all these events, we need only to trigger if any input or output property got changed. This will prevent the presentation/child component from updating the state.
In "employee-component.ts", add the below line to implement the change detection strategy.
- changeDetection: ChangeDetectionStrategy.OnPush
Codes
Added below codes for your reference:
employee.module.ts:
- import { NgModule } from '@angular/core';
- import { CommonModule } from '@angular/common';
- import { EmployeeComponent } from './employee.component';
- import { EmployeeDetailComponent } from './employee-detail/employee-detail.component';
-
- @NgModule({
- declarations: [EmployeeComponent, EmployeeDetailComponent],
- imports: [
- CommonModule
- ],
- exports: [EmployeeComponent]
- })
- export class EmployeeModule { }
employee.component.ts:
- import { Component, OnInit } from '@angular/core';
-
- @Component({
- selector: 'app-employee',
- templateUrl: './employee.component.html',
- styleUrls: ['./employee.component.css']
- })
- export class EmployeeComponent implements OnInit {
-
- public employeeData: any;
-
- constructor() { }
-
- ngOnInit(): void {
- this.employeeData = {
- name : 'Test EmployeeName',
- email: '[email protected]'
- };
- console.log(this.employeeData.name);
- }
-
- changed(employeeData: any){
- this.employeeData = employeeData;
- }
- }
employee.component.html
- <p>Employee</p>
- <app-employee-detail [employeeData]="employeeData" (employeeChanged)='changed($event)'></app-employee-detail>
employee-detail.component.ts,
- import { Component, OnInit, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
-
- @Component({
- selector: 'app-employee-detail',
- templateUrl: './employee-detail.component.html',
- styleUrls: ['./employee-detail.component.css'],
- changeDetection: ChangeDetectionStrategy.OnPush
- })
-
- export class EmployeeDetailComponent implements OnInit {
-
- @Input() public employeeData: any;
-
- @Output() public employeeChanged = new EventEmitter<any>();
-
- constructor() { }
-
- ngOnInit(): void {
- }
-
- employeeChange(){
- console.log(this.employeeData.name);
- this.employeeData.name = 'Name Changed from EmployeeDetail';
- this.employeeChanged.emit(this.employeeData);
- }
- }
employee-detail.component.html:
- Name: {{employeeData.name}}
- <br/>
- Email: {{employeeData.email}}
- <br/>
- <button (click)="employeeChange()">Update Employee</button>
Summary
In this post we learned about "Container(parent)" component and "Presentation(child)" components. We looked at how these components communicate with each other and saw the importance of change detection strategies.