The HostListener decorator is used to set up an event binding on the host element and is applied to a method. The example directive relies on the browser’s DOM API to manipulate its host element, both to add and remove class memberships and to receive the click event. Working with the DOM API in an Angular application is a useful technique, but it does mean that your directive can be used only in applications that are run in a web browser. Angular is intended to be run in a range of different execution environments, and not all of them can be assumed to provide the DOM API.
Even if you are sure that a directive will have access to the DOM, the same results can be achieved in a more elegant way using standard Angular directive features: property and event bindings. Rather than use the DOM to add and remove classes, a class binding can be used on the host element. And rather than use the addEventListener method, an event binding can be used to deal with the mouse click.
Behind the scenes, Angular implements these features using the DOM API when the directive is used in a web browser—or some equivalent mechanism when the directive is used in a different environment.
Bindings on the host element are defined using two decorators, @HostBinding and @HostListener, both of which are defined in the @angular/core module, as shown in the following example.
Creating Host Bindings in the attr.directive.ts File in the src/app Folder
import { Directive, ElementRef, Attribute, Input,
SimpleChange, Output, EventEmitter, HostListener, HostBinding }
from "@angular/core";
import { Product } from "./product.model";
@Directive({
selector: "[pa-attr]"
})
export class PaAttrDirective {
@Input("pa-attr")
@HostBinding("class")
bgClass: string;
@Input("pa-product")
product: Product;
@Output("pa-category")
click = new EventEmitter<string>();
@HostListener("click")
triggerCustomEvent() {
if (this.product != null) {
this.click.emit(this.product.category);
}
}
The @HostBinding decorator is used to set up a property binding on the host element and is applied to a directive property. The listing sets up a binding between the class property on the host element and the decorator’s bgClass property.
The @HostListener decorator is used to set up an event binding on the host element and is applied to a method. The listing creates an event binding for the click event that invokes the triggerCustomEvent method when the mouse button is pressed and released. As its name suggests, the triggerCustomEvent method uses the EventEmitter.emit method to dispatch the custom event through the output property.
Using the host element bindings means that the directive constructor can be removed since there is no longer any need to access the HTML element via the ElementRef object. Instead, Angular takes care of setting up the event listener and setting the element’s class membership through the property binding.
Although the directive code is much simpler, the effect of the directive is the same: clicking a table row sets the value of one of the input elements, and adding a new item using the form triggers a change in the background color of the table cells for products that are not part of the Soccer category.
What is HostListener in angular?
The HostListener decorator is used to set up an event binding on the host element and is applied to a method. In the hostlistener a set of arugments pass to the handler method when the event is occurs.
Hostlistener Events
Hostlistener Events is performing then the Hostlistener passes the arguments to the handler method that is already set. this is allowed to the registration of different event handlers on the elements. Events normally used with the functions and functions will not run before the events occur like when a button is clicked then the function will perform. Here is the List of Hostlistener Events.
Event | Description | Belongs To |
---|---|---|
Abort | The event occurs when the loading of a media is aborted | UiEvent, Event |
Afterprint | The event occurs when a page has started printing, or if the print dialogue box has been closed | Event |
animationend | The event occurs when a CSS animation has completed | AnimationEvent |
animationiteration | The event occurs when a CSS animation is repeated | AnimationEvent |
animationstart | The event occurs when a CSS animation has started | AnimationEvent |
beforeprint | The event occurs when a page is about to be printed | Event |
beforeunload | The event occurs before the document is about to be unloaded | UiEvent, Event |
blur | The event occurs when an element loses focus | FocusEvent |
canplay | The event occurs when the browser can start playing the media (when it has buffered enough to begin) | Event |
canplaythrough | The event occurs when the browser can play through the media without stopping for buffering | Event |
change | The event occurs when the content of a form element, the selection, or the checked state have changed (for <input>, <select>, and <textarea>) | Event |
click | The event occurs when the user clicks on an element | MouseEvent |
contextmenu | The event occurs when the user right-clicks on an element to open a context menu | MouseEvent |
copy | The event occurs when the user copies the content of an element | ClipboardEvent |
cut | The event occurs when the user cuts the content of an element | ClipboardEvent |
dblclick | The event occurs when the user double-clicks on an element | MouseEvent |
drag | The event occurs when an element is being dragged | DragEvent |
dragend | The event occurs when the user has finished dragging an element | DragEvent |
dragenter | The event occurs when the dragged element enters the drop target | DragEvent |
dragleave | The event occurs when the dragged element leaves the drop target | DragEvent |
dragover | The event occurs when the dragged element is over the drop target | DragEvent |
dragstart | The event occurs when the user starts to drag an element | DragEvent |
drop | The event occurs when the dragged element is dropped on the drop target | DragEvent |
durationchange | The event occurs when the duration of the media is changed | Event |
ended | The event occurs when the media has reach the end (useful for messages like “thanks for listening”) | Event |
error | The event occurs when an error occurs while loading an external file | ProgressEvent, UiEvent, Event |
focus | The event occurs when an element gets focus | FocusEvent |
focusin | The event occurs when an element is about to get focus | FocusEvent |
focusout | The event occurs when an element is about to lose focus | FocusEvent |
fullscreenchange | The event occurs when an element is displayed in fullscreen mode | Event |
fullscreenerror | The event occurs when an element can not be displayed in fullscreen mode | Event |
hashchange | The event occurs when there has been changes to the anchor part of a URL | HashChangeEvent |
input | The event occurs when an element gets user input | InputEvent, Event |
invalid | The event occurs when an element is invalid | Event |
keydown | The event occurs when the user is pressing a key | KeyboardEvent |
keypress | The event occurs when the user presses a key | KeyboardEvent |
keyup | The event occurs when the user releases a key | KeyboardEvent |
load | The event occurs when an object has loaded | UiEvent, Event |
loadeddata | The event occurs when media data is loaded | Event |
loadedmetadata | The event occurs when meta data (like dimensions and duration) are loaded | Event |
loadstart | The event occurs when the browser starts looking for the specified media | ProgressEvent |
message | The event occurs when a message is received through the event source | Event |
mousedown | The event occurs when the user presses a mouse button over an element | MouseEvent |
mouseenter | The event occurs when the pointer is moved onto an element | MouseEvent |
mouseleave | The event occurs when the pointer is moved out of an element | MouseEvent |
mousemove | The event occurs when the pointer is moving while it is over an element | MouseEvent |
mouseover | The event occurs when the pointer is moved onto an element, or onto one of its children | MouseEvent |
mouseout | The event occurs when a user moves the mouse pointer out of an element, or out of one of its children | MouseEvent |
mouseup | The event occurs when a user releases a mouse button over an element | MouseEvent |
mousewheel | Deprecated. Use the wheel event instead | WheelEvent |
offline | The event occurs when the browser starts to work offline | Event |
online | The event occurs when the browser starts to work online | Event |
open | The event occurs when a connection with the event source is opened | Event |
pagehide | The event occurs when the user navigates away from a webpage | PageTransitionEvent |
pageshow | The event occurs when the user navigates to a webpage | PageTransitionEvent |
paste | The event occurs when the user pastes some content in an element | ClipboardEvent |
pause | The event occurs when the media is paused either by the user or programmatically | Event |
play | The event occurs when the media has been started or is no longer paused | Event |
playing | The event occurs when the media is playing after having been paused or stopped for buffering | Event |
popstate | The event occurs when the window’s history changes | PopStateEvent |
progress | The event occurs when the browser is in the process of getting the media data (downloading the media) | Event |
ratechange | The event occurs when the playing speed of the media is changed | Event |
resize | The event occurs when the document view is resized | UiEvent, Event |
reset | The event occurs when a form is reset | Event |
scroll | The event occurs when an element’s scrollbar is being scrolled | UiEvent, Event |
search | The event occurs when the user writes something in a search field (for <input=”search”>) | Event |
seeked | The event occurs when the user is finished moving/skipping to a new position in the media | Event |
seeking | The event occurs when the user starts moving/skipping to a new position in the media | Event |
select | The event occurs after the user selects some text (for <input> and <textarea>) | UiEvent, Event |
show | The event occurs when a <menu> element is shown as a context menu | Event |
stalled | The event occurs when the browser is trying to get media data, but data is not available | Event |
storage | The event occurs when a Web Storage area is updated | StorageEvent |
submit | The event occurs when a form is submitted | Event |
suspend | The event occurs when the browser is intentionally not getting media data | Event |
timeupdate | The event occurs when the playing position has changed (like when the user fast forwards to a different point in the media) | Event |
toggle | The event occurs when the user opens or closes the <details> element | Event |
touchcancel | The event occurs when the touch is interrupted | TouchEvent |
touchend | The event occurs when a finger is removed from a touch screen | TouchEvent |
touchmove | The event occurs when a finger is dragged across the screen | TouchEvent |
touchstart | The event occurs when a finger is placed on a touch screen | TouchEvent |
transitionend | The event occurs when a CSS transition has completed | TransitionEvent |
unload | The event occurs once a page has unloaded (for <body>) | UiEvent, Event |
volumechange | The event occurs when the volume of the media has changed (includes setting the volume to “mute”) | Event |
waiting | The event occurs when the media has paused but is expected to resume (like when the media pauses to buffer more data) | Event |
wheel | The event occurs when the mouse wheel rolls up or down over an element | WheelEvent |
Creating a Two-Way Binding using Hostlistener & HostBinding
Angular provides special support for creating directives that support two-way bindings so they can be used with the banana-in-a-box bracket style that ngModel uses and can bind to a model property in both directions.
The two-way binding feature relies on a naming convention. To demonstrate how it works, the following example adds some new elements and bindings to the template.html file.
Applying a Directive in the template.html File in the src/app Folder
...
<div class="col-6">
<div class="form-group bg-info text-white p-2">
<label>Name:</label>
<input class="bg-primary text-white" [paModel]="newProduct.name"
(paModelChange)="newProduct.name=$event" />
</div>
<table class="table table-sm table-bordered table-striped">
<tr><th></th><th>Name</th><th>Category</th><th>Price</th></tr>
<tr *ngFor="let item of getProducts(); let i = index"
[pa-attr]="getProducts().length < 6 ? 'bg-success' : 'bg-warning'"
[pa-product]="item" (pa-category)="newProduct.category=$event">
<td>{{i + 1}}</td>
<td [pa-attr]="item.category == 'Soccer' ? 'bg-info' : null">
{{item.category}}
</td>
<td [pa-attr]="'bg-info'">{{item.price}}</td>
</tr>
</table>
</div>
...
I am going to create a directive that supports two one-way bindings. The binding whose target is paModel will be updated when the value of the newProduct.name property changes, which provides a flow of data from the application to the directive and will be used to update the contents of the input element. The custom event, paModelChange, will be triggered when the user changes the contents of the input element and will provide a flow of data from the directive to the rest of the application.
To implement the directive, I added a file called twoway.directive.ts to the src/app folder and used it to define the directive shown in the following example.
The Contents of the twoway.directive.ts File in the src/app Folder
import { Input, Output, EventEmitter, Directive,
HostBinding, HostListener, SimpleChange } from "@angular/core";
@Directive({
selector: "input[paModel]"
})
export class PaModel {
@Input("paModel")
modelProperty: string;
@HostBinding("value")
fieldValue: string = "";
ngOnChanges(changes: { [property: string]: SimpleChange }) {
let change = changes["modelProperty"];
if (change.currentValue != this.fieldValue) {
this.fieldValue = changes["modelProperty"].currentValue || "";
}
}
@Output("paModelChange")
update = new EventEmitter<string>();
@HostListener("input", ["$event.target.value"])
updateValue(newValue: string) {
this.fieldValue = newValue;
this.update.emit(newValue);
}
}
This directive uses features that have been described previously. The selector property for this directive specifies that it will match input elements that have a paModel attribute. The built-in ngModel two-way directive has support for a range of form elements and knows which events and properties each of them uses, but I want to keep this example simple, so I am going to support just input elements, which define a value property that gets and sets the element content.
The paModel binding is implemented using an input property and the ngOnChanges method, which responds to changes in the expression value by updating the contents of the input element through a host binding on the input element’s value property.
The paModelChange event is implemented using a host listener on the input event, which then sends an update through an output property. Notice that the method invoked by the event is able to receive the event object by specifying an additional argument to the @HostListener decorator, like this:
...
@HostListener("input", ["$event.target.value"])
updateValue(newValue: string) {
...
The first argument to the @HostListener decorator specifies the name of the event that will be handled by the listener. The second argument is an array that will be used to provide the decorated methods with arguments. In this example, the input event will be handled by the listener, and when the updateValue method is invoked, its newValue argument will be set to the target. value property of the Event object, which is referred to using $event.
To enable the directive, I added it to the Angular module, as shown in the following example.
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { ProductComponent } from "./component";
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { PaAttrDirective } from "./attr.directive";
import { PaModel } from "./twoway.directive";
@NgModule({
imports: [BrowserModule, FormsModule, ReactiveFormsModule],
declarations: [ProductComponent, PaAttrDirective, PaModel],
bootstrap: [ProductComponent]
})
export class AppModule { }
When you save the changes and the browser has reloaded, you will see a new input element that responds to changes to a model property and updates the model property if its host element’s content is changed. The expressions in the bindings specify the same model property used by the Name field in the form on the left side of the HTML document, which provides a convenient way to test the relationship between them, as shown in the following image.
The final step is to simplify the bindings and apply the banana-in-a-box style of brackets, as shown in the following example.
...
<div class="col-6">
<div class="form-group bg-info text-white p-2">
<label>Name:</label>
<input class="bg-primary text-white" [(paModel)]="newProduct.name" />
</div>
<table class="table table-sm table-bordered table-striped">
<tr><th></th><th>Name</th><th>Category</th><th>Price</th></tr>
<tr *ngFor="let item of getProducts(); let i = index"
[pa-attr]="getProducts().length < 6 ? 'bg-success' : 'bg-warning'"
[pa-product]="item" (pa-category)="newProduct.category=$event">
<td>{{i + 1}}</td>
<td>{{item.name}}</td>
<td [pa-attr]="item.category == 'Soccer' ? 'bg-info' : null">
{{item.category}}
</td>
<td [pa-attr]="'bg-info'">{{item.price}}</td>
</tr>
</table>
</div>
...
When Angular encounters the [()] brackets, it expands the binding to match the format used in the above example, targeting the paModel input property and setting up the paModelChange event. As long as a directive exposes these to Angular, it can be targeted using the banana-in-a-box brackets, producing a simpler template syntax.
Reference
https://angular.io/api/core/HostListener
Visit the angular tutorial list. And make strong your angular concept. click here. wuschools.com is always written about the Agular concept for the angular lover. Ang writes about how angular makes your life easy if you are a web site developer.