Using HostListener And HostBinding in Angular

Using HostListener And HostBinding in Angular

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.

EventDescriptionBelongs To
AbortThe event occurs when the loading of a media is abortedUiEvent, Event
AfterprintThe event occurs when a page has started printing, or if the print dialogue box has been closedEvent
animationendThe event occurs when a CSS animation has completedAnimationEvent
animationiterationThe event occurs when a CSS animation is repeatedAnimationEvent
animationstartThe event occurs when a CSS animation has startedAnimationEvent
beforeprintThe event occurs when a page is about to be printedEvent
beforeunloadThe event occurs before the document is about to be unloadedUiEvent, Event
blurThe event occurs when an element loses focusFocusEvent
canplayThe event occurs when the browser can start playing the media (when it has buffered enough to begin)Event
canplaythroughThe event occurs when the browser can play through the media without stopping for bufferingEvent
changeThe event occurs when the content of a form element, the selection, or the checked state have changed (for <input>, <select>, and <textarea>)Event
clickThe event occurs when the user clicks on an elementMouseEvent
contextmenuThe event occurs when the user right-clicks on an element to open a context menuMouseEvent
copyThe event occurs when the user copies the content of an elementClipboardEvent
cutThe event occurs when the user cuts the content of an elementClipboardEvent
dblclickThe event occurs when the user double-clicks on an elementMouseEvent
dragThe event occurs when an element is being draggedDragEvent
dragendThe event occurs when the user has finished dragging an elementDragEvent
dragenterThe event occurs when the dragged element enters the drop targetDragEvent
dragleaveThe event occurs when the dragged element leaves the drop targetDragEvent
dragoverThe event occurs when the dragged element is over the drop targetDragEvent
dragstartThe event occurs when the user starts to drag an elementDragEvent
dropThe event occurs when the dragged element is dropped on the drop targetDragEvent
durationchangeThe event occurs when the duration of the media is changedEvent
endedThe event occurs when the media has reach the end (useful for messages like “thanks for listening”)Event
errorThe event occurs when an error occurs while loading an external fileProgressEvent, UiEvent, Event
focusThe event occurs when an element gets focusFocusEvent
focusinThe event occurs when an element is about to get focusFocusEvent
focusoutThe event occurs when an element is about to lose focusFocusEvent
fullscreenchangeThe event occurs when an element is displayed in fullscreen modeEvent
fullscreenerrorThe event occurs when an element can not be displayed in fullscreen modeEvent
hashchangeThe event occurs when there has been changes to the anchor part of a URLHashChangeEvent
inputThe event occurs when an element gets user inputInputEvent, Event
invalidThe event occurs when an element is invalidEvent
keydownThe event occurs when the user is pressing a keyKeyboardEvent
keypressThe event occurs when the user presses a keyKeyboardEvent
keyupThe event occurs when the user releases a keyKeyboardEvent
loadThe event occurs when an object has loadedUiEvent, Event
loadeddataThe event occurs when media data is loadedEvent
loadedmetadataThe event occurs when meta data (like dimensions and duration) are loadedEvent
loadstartThe event occurs when the browser starts looking for the specified mediaProgressEvent
messageThe event occurs when a message is received through the event sourceEvent
mousedownThe event occurs when the user presses a mouse button over an elementMouseEvent
mouseenterThe event occurs when the pointer is moved onto an elementMouseEvent
mouseleaveThe event occurs when the pointer is moved out of an elementMouseEvent
mousemoveThe event occurs when the pointer is moving while it is over an elementMouseEvent
mouseoverThe event occurs when the pointer is moved onto an element, or onto one of its childrenMouseEvent
mouseoutThe event occurs when a user moves the mouse pointer out of an element, or out of one of its childrenMouseEvent
mouseupThe event occurs when a user releases a mouse button over an elementMouseEvent
mousewheelDeprecated. Use the wheel event insteadWheelEvent
offlineThe event occurs when the browser starts to work offlineEvent
onlineThe event occurs when the browser starts to work onlineEvent
openThe event occurs when a connection with the event source is openedEvent
pagehideThe event occurs when the user navigates away from a webpagePageTransitionEvent
pageshowThe event occurs when the user navigates to a webpagePageTransitionEvent
pasteThe event occurs when the user pastes some content in an elementClipboardEvent
pauseThe event occurs when the media is paused either by the user or programmaticallyEvent
playThe event occurs when the media has been started or is no longer pausedEvent
playingThe event occurs when the media is playing after having been paused or stopped for bufferingEvent
popstateThe event occurs when the window’s history changesPopStateEvent
progressThe event occurs when the browser is in the process of getting the media data (downloading the media)Event
ratechangeThe event occurs when the playing speed of the media is changedEvent
resizeThe event occurs when the document view is resizedUiEvent, Event
resetThe event occurs when a form is resetEvent
scrollThe event occurs when an element’s scrollbar is being scrolledUiEvent, Event
searchThe event occurs when the user writes something in a search field (for <input=”search”>)Event
seekedThe event occurs when the user is finished moving/skipping to a new position in the mediaEvent
seekingThe event occurs when the user starts moving/skipping to a new position in the mediaEvent
selectThe event occurs after the user selects some text (for <input> and <textarea>)UiEvent, Event
showThe event occurs when a <menu> element is shown as a context menuEvent
stalledThe event occurs when the browser is trying to get media data, but data is not availableEvent
storageThe event occurs when a Web Storage area is updatedStorageEvent
submitThe event occurs when a form is submittedEvent
suspendThe event occurs when the browser is intentionally not getting media dataEvent
timeupdateThe event occurs when the playing position has changed (like when the user fast forwards to a different point in the media)Event
toggleThe event occurs when the user opens or closes the <details> elementEvent
touchcancelThe event occurs when the touch is interruptedTouchEvent
touchendThe event occurs when a finger is removed from a touch screenTouchEvent
touchmoveThe event occurs when a finger is dragged across the screenTouchEvent
touchstartThe event occurs when a finger is placed on a touch screenTouchEvent
transitionendThe event occurs when a CSS transition has completedTransitionEvent
unloadThe event occurs once a page has unloaded (for <body>)UiEvent, Event
volumechangeThe event occurs when the volume of the media has changed (includes setting the volume to “mute”)Event
waitingThe event occurs when the media has paused but is expected to resume (like when the media pauses to buffer more data)Event
wheelThe event occurs when the mouse wheel rolls up or down over an elementWheelEvent

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.

hostlistener
hostlistener

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.

Leave a Reply