The HostBinding & HostListener are decorators in Angular. HostListener listens to host events, while HostBinding allows us to bind to a property of the host element. The host is an element on which we attach our component or directive. This feature allows us to manipulate the host styles or take some action whenever the user performs some action on the host element.
The host element is the element on which we attach our directive or component . Remember components are directives with a view (template).
For Example
Consider the following ttToggle directive. We built this directive in our tutorial custom directive in Angular . We attach it to a button element. Here the button element is the host element.
<button ttToggle>Click To Toggle</button>
In the following example for the apphighlight directive, p element is the host element
<div>
<p apphighlight>
<div>This text will be highlighted</div>
</p>
</div>
Host Binding binds a Host element property to a variable in the directive or component
The following appHighLight directive, uses the HostBinding on style.border property of the parent element to the border property.
import { Directive, HostBinding, OnInit } from '@angular/core'
@Directive({
selector: '[appHighLight]',
})
export class HighLightDirective implements OnInit {
@HostBinding('style.border') border: string;
ngOnInit() {
this.border="5px solid blue"
}
}
We apply appHighLight directive to a host element ( p in the example) as shown below.
<div>
<h2>appHighLight Directive</h2>
<p appHighLight>
This Text has blue Border
</p>
</div>
HostListener Decorator listens to the DOM event on the host element. It also provides a handler method to run when that event occurs.
For example, in the following code HostListener listens to the mouseover & mouseleave event. We use the HostListner decorator to decorate functions onMouseOver & onMouseLeave.
import { Directive, HostBinding, OnInit, HostListener } from '@angular/core'
@Directive({
selector: '[appHighLight]',
})
export class HighLightDirective implements OnInit {
@HostBinding('style.border') border: string;
ngOnInit() {
}
@HostListener('mouseover')
onMouseOver() {
this.border = '5px solid green';
console.log("Mouse over")
}
@HostListener('mouseleave')
onMouseLeave() {
this.border = '';
console.log("Mouse Leave")
}
}
We apply the directive on a host element (p in the example) as shown below.
Whenever the mouse is moved over the p element, the mouseover event is captured by the HostListener. It runs the onMouseOver method which we have attached to it. This method adds a green border to the p element using the HostBinding.
Similarly, on mouseleave event, the border is removed.
<div>
<h2>appHighLight Directive</h2>
<p appHighLight>
This Text has blue Border
</p>
</div>
Attaching a class to the host element is one of the common use cases of the HostBinding decorator.
For Example the following example adds the highlight & box class to the host element
@HostBinding('class') class: string;
ngOnInit() {
this.class="highlight box"
}
You can also Use the getter method.
@HostBinding('class') get class() { return "highlight box" }
Another example
@HostBinding('class.highlight') get hasHighlight () { return true; }
@HostBinding('class.box') get hasBox () { return false }
The Classes that HostBinding adds must exist in the scope of the host. i.e. both
highlight & box must exist in the global styles or in the
Component where we add the directive.
The components are nothing but directives with a template. Hence we can make use of both HostBinding & HostListner in components also.
The following is a BoxComponent, which applies the highlight & box classes to the host element. The classes highlight & box are defined in the component.
import { Component, HostBinding, HostListener } from '@angular/core';
@Component({
selector: 'app-box',
template: `
<h2> This is Box Component</h2> `,
styles: [
`
.highlight {
color:green;
display: block;
}
.box {
border: 1px dashed green;
}
`
],
})
export class BoxComponent {
title = 'hostBinding';
@HostBinding('class.highlight') get hasHighlight() { return true; }
@HostBinding('class.box') get hasBox() { return true }
}
Now, open the app.component.ts and insert the above component.
<app-box></app-box>
Run the app and you will not see any border neither the text is highlighted. i.e. because the host element exists in the parent components (AppComponent) scope and not in the BoxComponent scope. So any CSS styles in the BoxComponent will have no effect
Open the app.component.css and add the styles. These styles are now applied correctly.
.highlight {
color:blue;
display: block;
}
.box {
border: 1px solid red;
}