Follow the below steps for passing data from a component using the
@Output method.
Step 1 -
Open the star component in the sample application and add the @Output and EventEmitter to the import statement as shown in the code below.
star.component.ts
[c]
import { Component, OnChanges, Input,
Output, EventEmitter } from '@angular/core';
@Component({
selector: 'sp-star',
templateUrl: 'app/shared/star.component.html',
styleUrls: ['app/shared/star.component.css']
})
export class StarComponent {
@Input() rating: number;
starWidth: number;
@Output() ratingClicked: EventEmitter<string> =
new EventEmitter<string>();
ngOnChanges(): void {
this.starWidth = this.rating * 86/5;
}
}
[/c]
Here in the code, in order to expose an event to the container, a ratingClicked event property is defined and the property type is defined to be an EventEmitter, and the event payload is a string, so specified "string" as the generic argument. Set the ratingClicked property to new instance of EventEmitter. Decorate this property with the @Output decorator to expose it so that the container can respond to this event. The @Output decorator is a function so add parenthesis. In this example only one property of the nested component is decorated with the @Output decorator but it is not limited to one and can expose multiple output properties as needed.
Step 2 -
Now open the star component template and use event binding to bind the div element’s clicked event to a local onClick method.
star.component.html
[html]
<div class="crop"
[style.width.px]="starWidth"
="rating"
(click)='onClick()'>
<div style="width: 86px">
<span class="glyphicon glyphicon-star"></span>
<span class="glyphicon glyphicon-star"></span>
<span class="glyphicon glyphicon-star"></span>
<span class="glyphicon glyphicon-star"></span>
<span class="glyphicon glyphicon-star"></span>
</div>
</div>
[/html]
Step 3 -
Now implement this onClick method in the star component as shown in the code below.
star.component.ts
[c]
import { Component, OnChanges, Input,
Output, EventEmitter } from '@angular/core';
@Component({
selector: 'sp-star',
templateUrl: 'app/shared/star.component.html',
styleUrls: ['app/shared/star.component.css']
})
export class StarComponent {
@Input() rating: number;
starWidth: number;
@Output() ratingClicked: EventEmitter<string> =
new EventEmitter<string>();
ngOnChanges(): void {
this.starWidth = this.rating * 86/5;
}
onClick(): void {
this.ratingClicked.emit(`The rating ${this.rating} was clicked!`);
}
}
[/c]
When the star component process the clicked event on the div, it wants to raise an event to the container and pass along a message, an event property is used and call it’s emit method by passing in the desired string, in this example code, the ES2015 back text is used to define a template string which allows users to bind the rating directly into the string using the dollar syntax.
Step 4 -
Now, open the product list component template and in the nested components directive add event binding respond to the ratingClicked event exposed by the star component and one can get the event payload, respond by calling the own local method like onRatingClicked and the event payload is available using the $event, so pass that in to the onRatingClicked method as shown in the code below.
product-list.component.html
[html]
<div class='panel panel-primary'>
<div class='panel-heading'>
{ {pageTitle}}
</div>
<div class='panel-body'>
<div class='row'>
<div class='col-md-2'>Filter by:</div>
<div class='col-md-4'>
<input type='text'
[(ngModel)]='listFilter' />
</div>
</div>
<div class ='row'>
<div class='col-md-6'>
<h3>Filtered by: { {listFilter}}</h3>
</div>
</div>
<div class='table-responsive'>
<table class='table'
*ngIf='products && products.length'>
<thead>
<tr>
<th>
<button class='btn btn-success'
(click)='toggleImage()'>
{ {showImage ? 'Hide' : 'Show'}} Image
</button>
</th>
<th>Product</th>
<th>Code</th>
<th>Available</th>
<th>Price</th>
<th>5 Star Rating</th>
</tr>
</thead>
<tbody>
<tr *ngFor='let product of products | productFilter:listFilter'>
<td>
<img *ngIf='showImage'
[src]='product.imageUrl'
='product.productName'
[style.width.px]='imageWidth'
[style.margin.px]='imageMargin'>
</td>
<td>{ { product.productName }}</td>
<td>{ { product.productCode | lowercase }}</td>
<td>{ { product.releaseDate }}</td>
<td>{ { product.price | currency:'USD':true:'1.2-2'}}</td>
<td>
<sp-star [rating]='product.starRating'
(ratingClicked)='onRatingClicked($event)'>
</sp-star>
</td>
</tbody>
</table>
</div>
</div>
[/html]
Step 5 -
Now, write the code for the new
onRatingClicked method in the container’s class. So, open the product list component and define the
onRatingClicked method as shown in the below code.
product-list.component.ts
[c]
import { Component, OnInit } from '@angular/core';
import { IProduct } from './product';
@Component({
selector: 'pm-products',
templateUrl: 'app/products/product-list.component.html',
styleUrls: ['app/products/product-list.component.css']
})
export class ProductListComponent implements OnInit{
pageTitle: string = 'Product List!';
imageWidth: number = 50;
imageMargin: number = 2;
showImage: boolean = false;
listFilter: string = 'angular';
products: IProduct[] = [
{
"productId": 1,
"productName": "Angular 2",
"productCode": "SPL-0011",
"releaseDate": "March 19, 2016",
"description": "A Practical Introduction to the new Web Development Platform Angular 2",
"price": 19.95,
"starRating": 3.2,
"imageUrl": "./app/assets/images/angular_2.png"
},
{
"productId": 2,
"productName": "Word Press",
"productCode": "SPL-0023",
"releaseDate": "March 18, 2016",
"description": "This ebook allows you to create a WordPress website on your domainfrom scratch.",
"price": 32.99,
"starRating": 4.2,
"imageUrl": "./app/assets/images/wordpress-logo.png"
}
];
toggleImage(): void{
this.showImage = !this.showImage;
}
ngOnInit(): void {
console.log('In OnInit');
}
onRatingClicked(message: string): void {
this.pageTitle = 'Product List: ' + message;
}
}
[/c]
Here in the code, a
message: string parameter is defined for the event payload, the
pageTiltle is modified in order to display the “
Product List” and the message from the nested component.