Angular - Featured and Presentation Component
In this article, lets learn the featured and presentation components. It may also be refered as
- Smart and Dump Components
- Featured and Presentation Components
Featured Components
Featured Components are the components which will be acting as the parent component holding all other components which can be referred to as child components. The featured components are the components which are responsible for gathering data from different services and providing the data to its child component. This performs smart work by collecting data, transferring data to its child components and taking actions based on the event raised by its child components.
Presentation Components
These are the components, which receives the data from the featured components and use those data to populate a list or any other operation with those data. These components are responsible only to present information provided by the featured component. These components does not perform any business logic. If needed to perform any business logic it has to communicate with the featured component by raising an event and notifying the parent component.
Normally presentation component get data from featured component through @Input()
and raises an event using @Output()
to notify the featured component to perform any action.
Let's start with an example program
Create a new angular project
Create a new angular application using
ng new angular-app
Enter into the project using
cd angular-app
Once the application has been created using angular cli command, to check the initial result of the application enter.
ng serve --o
Create a service and modify the code
ng g s services/product
This will create a ProductService
in services folder with some boilerplate code. Modify the code as below.
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class ProductService {
private products: { name: string }[] = [
{ name: 'Apple' },
{ name: 'Asus' },
{ name: 'HP' },
{ name: 'Acer' }
];
constructor() { }
getProducts() {
return this.products;
}
removeProduct(productName: string) {
const index = this.products.findIndex((value) => {
return value.name === productName;
});
console.log(index);
if (index > -1) {
this.products.splice(index, 1);
}
}
}
The ProductService
will have a list of products and will perform 2 functionality with getProducts()
function and removeProduct()
function.
getProducts()
- Will return the list of productsremoveProduct()
- Will remove the product from the list based on the product name.
Create a Presentation Component
Enter the following angular cli command to create a component to act as presentation component.
ng g c product
After the component is created, modify the product.component.ts
file with product @Input()
and select @Output()
.
import { Component, OnInit, Input, EventEmitter, Output } from '@angular/core';
@Component({
selector: 'app-product',
templateUrl: './product.component.html',
styleUrls: ['./product.component.css']
})
export class ProductComponent implements OnInit {
@Input() product;
// tslint:disable-next-line: no-output-native
@Output() select = new EventEmitter<any>();
constructor() { }
ngOnInit() {
}
removeProduct() {
this.select.emit(this.product.name);
}
}
Modify the product.component.html
file with the following code.
<p>
<button (click)='removeProduct()'>Remove</button>
Product Name : <span>{{product.name}} </span>
</p>
The product @Input()
will receive the product name from its parent(Featured) component which will be displayed in its template insida a p
tag.
When clicking on Remove
button, it will call the removeProduct()
function. The removeProduct()
function will use the select
event emitter to emit an event to its parent with the name
of the product.
Create a Featured Component
Create a featured component, ProductListComponent
to list the products.
ng g c product-list
Once the component is created, modify the product-list.component.ts
file code to get the product list from ProductService
.
import { Component, OnInit } from '@angular/core';
import { ProductService } from '../services/product.service';
@Component({
selector: 'app-product-list',
templateUrl: './product-list.component.html',
styleUrls: ['./product-list.component.css']
})
export class ProductListComponent implements OnInit {
products: { name: string }[];
constructor(private productService: ProductService) { }
ngOnInit() {
this.products = this.productService.getProducts();
console.log(this.products);
}
removeProduct(productName) {
this.productService.removeProduct(productName);
}
}
Here, we have injected the ProductService
to the constructor and called the getProducts()
function to get the list of products and assign it to the local products
variable.
The removeProduct
function will get the productName
as input and calls the removeProduct
function of ProductService
to remove the product from the product list.
Below is the template of the ProductList
component.
<div class="container">
<ng-container *ngIf='products && products.length>0'>
<ng-container *ngFor='let product of products'>
<app-product [product]='product' (select)='removeProduct($event)'></app-product>
</ng-container>
</ng-container>
</div>
Here we loop through the products list and add the ProductComponent's selector string with product @Input()
and select @Output()
.
In the @Input()
, the featured component will provide the product detail to the presentation component which is ProductComponent
.
In the @Output()
when the ProductComponent
emits an event then Product function will be called in ProductListComponent
which is the featured component. This will in-turn remove the product from the product list.
If we notice the architecture, the ProductComponent
will just raise event and notify the ProductListComponent
rather than taking action of its own. So here ProductComponent
is a dump component which never perform any business logic.
This architecture is easy to be performed in a small scenario like this but in a complex scenario, like the child component may also have some child component so in such cases, we need to use the smart component to handle communication between the Featured and Presentation components.