262

In my meanderings around the world wide interweb, and now especially the angular.io style docs, I find many references to @HostBinding and @HostListener. It seems they are quite fundamental, but unfortunately the documentation for them at the moment is a little sketchy.

Can anyone please explain what they are, how they work and give an example of their usage?

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
serlingpa
  • 12,024
  • 24
  • 80
  • 130

9 Answers9

240

A quick tip that helps me remember what they do -

HostBinding('value') myValue; is exactly the same as [value]="myValue"

And

HostListener('click') myClick(){ } is exactly the same as (click)="myClick()"


HostBinding and HostListener are written in directives and the other ones (...) and [..] are written inside templates (of components).

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
Shai Reznik - HiRez.io
  • 8,748
  • 2
  • 33
  • 33
179

Have you checked these official docs?

HostListener - Declares a host listener. Angular will invoke the decorated method when the host element emits the specified event.

@HostListener - will listen to the event emitted by the host element that's declared with @HostListener.

HostBinding - Declares a host property binding. Angular automatically checks host property bindings during change detection. If a binding changes, it will update the host element of the directive.

@HostBinding - will bind the property to the host element, If a binding changes, HostBinding will update the host element.


NOTE: Both links have been removed recently. The "HostBinding-HostListening" portion of the style guide may be a useful alternative until the links return.


Here's a simple code example to help picture what this means:

DEMO : Here's the demo live in plunker - "A simple example about @HostListener & @HostBinding"

  • This example binds a role property -- declared with @HostBinding -- to the host's element
    • Recall that role is an attribute, since we're using attr.role.
    • <p myDir> becomes <p mydir="" role="admin"> when you view it in developer tools.
  • It then listens to the onClick event declared with @HostListener, attached to the component's host element, changing role with each click.
    • The change when the <p myDir> is clicked is that its opening tag changes from <p mydir="" role="admin"> to <p mydir="" role="guest"> and back.

directives.ts

import {Component,HostListener,Directive,HostBinding,Input} from '@angular/core';

@Directive({selector: '[myDir]'})
export class HostDirective {
    @HostBinding('attr.role') role = 'admin';
    @HostListener('click') onClick() {
        this.role= this.role === 'admin' ? 'guest' : 'admin';
    }
}

AppComponent.ts

import { Component,ElementRef,ViewChild } from '@angular/core';
import {HostDirective} from './directives';

@Component({
    selector: 'my-app',
    template:
        `
        <p myDir>
            Host Element 
            <br><br>
        
            We have a (HostListener) listening to this host's 
            <b>click event</b> declared with @HostListener
        
            <br><br>
        
            And we have a (HostBinding) binding <b>the role property</b>
            to host element declared with @HostBinding 
            and checking host's property binding updates.
            
            If any property change is found I will update it.
        </p>
        
        <div>
            View this change in the DOM of the host element 
            by opening developer tools, clicking the host element in the UI. 
        
            The role attribute's changes will be visible in the DOM.
        </div> 
        `,
    directives: [HostDirective]
})
export class AppComponent {}
Edu Müller
  • 435
  • 2
  • 5
  • 19
micronyks
  • 54,797
  • 15
  • 112
  • 146
  • 1
    are this decorator still used it seems the links have been removed from angular2 documentation – CommonSenseCode Sep 19 '16 at 19:12
  • 1
    Yes, it is still in use but let me confirm it once. I 'll update you, if I can figure out something else. – micronyks Sep 20 '16 at 02:06
  • They are on the cheat sheet: https://angular.io/docs/ts/latest/guide/cheatsheet.html – Targaryen Sep 21 '16 at 14:45
  • 1
    @Mr.EasyAnswersMcFly updated answer with note and link. Please note still proper documentation is not available. – micronyks Sep 22 '16 at 14:40
  • @micronyks For what you just said in the answer. Where can I find document for it? Thanks! – Nicolas S.Xu Nov 29 '16 at 20:59
  • Guys, Performance question.. If I used `@HostListener` with the window scroll event inside of a directive and there were multiple instances of that directive will the event listener be binded to all of the instances or it will only have one listener and run the methods inside of it ? – Muhammad Saleh Dec 25 '16 at 07:45
  • @MuhammadSaleh please show it practically its hard to guess and answer. – micronyks Dec 25 '16 at 07:49
  • @micronyks Please check this [Plunkr](https://plnkr.co/edit/DWwRFI07GNc95IbwyvYd?p=preview) Check it's console please In this example I have multiple instances of the same directive So my question is: does this mean that I will have multiple number of event listeners listening to the scroll event [bad performance I suppose] or Angular is smart enough to have one global window scroll event listener and just execute the methods inside, or it doesn't make a big difference ? – Muhammad Saleh Dec 25 '16 at 07:57
  • 1
    @MuhammadSaleh for scroll its hard to say that how it counts and calculates...but that is for sure that each instance will have a separate listener – micronyks Dec 25 '16 at 08:04
  • If anyone is looking for an example I found this a quick read and at the bottom you can cut and paste and play with the code - https://ng2.codecraft.tv/custom-directives/hostlistener-and-hostbinding/ – mtpultz Jul 06 '17 at 18:19
  • I don't think there is a `directives` attribute for `@Component` – tmjee Oct 26 '17 at 23:44
  • More information about @HostBinding you can find https://indepth.dev/posts/1429/making-hostbinding-work-with-observables – Varvara Sandakova Aug 12 '21 at 20:04
57

Here is a basic hover example.

Component's template property:

Template

<!-- attention, we have the c_highlight class -->
<!-- c_highlight is the selector property value of the directive -->

<p class="c_highlight">
    Some text.
</p>

And our directive

import {Component,HostListener,Directive,HostBinding} from '@angular/core';

@Directive({
    // this directive will work only if the DOM el has the c_highlight class
    selector: '.c_highlight'
 })
export class HostDirective {

  // we could pass lots of thing to the HostBinding function. 
  // like class.valid or attr.required etc.

  @HostBinding('style.backgroundColor') c_colorrr = "red"; 

  @HostListener('mouseenter') c_onEnterrr() {
   this.c_colorrr= "blue" ;
  }

  @HostListener('mouseleave') c_onLeaveee() {
   this.c_colorrr = "yellow" ;
  } 
}
j3ff
  • 5,719
  • 8
  • 38
  • 51
serkan
  • 6,885
  • 4
  • 41
  • 49
  • 33
    I do not see this accepted answer as an answer to the question asked. Would you care to provide some explanation? Like what c_colorrr, c_onEnterrr(), c_onLeaveeee do in this particular code snippet? – luqo33 May 05 '17 at 20:07
  • 1
    I thik it should change colour on mouse enter event to blue and on mouse leave event to yellow. – Michał Ziobro May 07 '17 at 21:00
  • Where do you place the directive in the markup? Seems you would place it on the body tag, but that would be outside the root component. If you're confused by the this answer this link might help https://ng2.codecraft.tv/custom-directives/hostlistener-and-hostbinding/ – mtpultz Jul 06 '17 at 17:57
  • @mtpultz It is in the class. – serkan Aug 06 '17 at 01:55
  • So is it only for directives?? – O'Rooney Mar 01 '23 at 20:44
39

Another nice thing about @HostBinding is that you can combine it with @Input if your binding relies directly on an input, eg:

@HostBinding('class.fixed-thing')
@Input()
fixed: boolean;
altschuler
  • 3,694
  • 2
  • 28
  • 55
24

Summary:

  • @HostBinding: This decorator binds a class property to a property of the host element.
  • @HostListener: This decorator binds a class method to an event of the host element.

Example:

import { Component, HostListener, HostBinding } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `<p>This is nice text<p>`,
})
export class AppComponent  {

  @HostBinding('style.color') color; 

  @HostListener('click')
  onclick() {
    this.color =  'blue';
  }

}

In the above example the following occurs:

  • An event listener is added to the click event which will be fired when a click event occurs anywhere within the component
  • The color property in our AppComponent class is bound to the style.color property on the component. So whenever the color property is updated so will the style.color property of our component
  • The result will be that whenever someone clicks on the component the color will be updated.

Usage in @Directive:

Although it can be used on component these decorators are often used in a attribute directives. When used in an @Directive the host changes the element on which the directive is placed. For example take a look at this component template:

<p p_Dir>some paragraph</p>

Here p_Dir is a directive on the <p> element. When @HostBinding or @HostListener is used within the directive class the host will now refer to the <p>.

Community
  • 1
  • 1
Willem van der Veen
  • 33,665
  • 16
  • 190
  • 155
16

One thing that adds confusion to this subject is the idea of decorators is not made very clear, and when we consider something like...

@HostBinding('attr.something') 
get something() { 
    return this.somethingElse; 
 }

It works, because it is a get accessor. You couldn't use a function equivalent:

@HostBinding('attr.something') 
something() { 
    return this.somethingElse; 
 }

Otherwise, the benefit of using @HostBinding is it assures change detection is run when the bound value changes.

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
10
// begginers
@Component({
  selector: 'custom-comp',
  template: ` <div class="my-class" (click)="onClick()">CLICK ME</div> `,
})
export class CustomComp {
  onClick = () => console.log('click event');
}

// pros
@Component({
  selector: 'custom-comp',
  template: ` CLICK ME `,
})
export class CustomComp {
  @HostBinding('class.my-class') className = true;
  @HostListener('click') onClick = () => this.className = false;
}

// experts
@Component({
  selector: 'custom-comp',
  template: ` CLICK ME `,
  host: {
    class: 'my-class',
    '(click)': 'onClick()',
  },
})
export class CustomComp {
  onClick = () => console.log('click event');
}

The 1st way will result in:

<custom-comp>
   <div class="my-class" (click)="onClick()">
      CLICK ME
   <div>
</custom-comp>

The 2nd and 3rd ways will result in:

<custom-comp class="my-class" (click)="onClick()">
   CLICK ME
</custom-comp>

NOTE: did you find the easter egg on the 2nd?

David Lopes
  • 227
  • 2
  • 10
  • 2
    Thank you for contributing an answer. Would you kindly edit your answer to to include an explanation of your code? That will help future readers better understand what is going on, and especially those members of the community who are new to the language and struggling to understand the concepts. – STA Feb 04 '21 at 15:13
6

Theory with less Jargons

@Hostlistnening deals basically with the host element say (a button) listening to an action by a user and performing a certain function say alert("Ahoy!") while @Hostbinding is the other way round. Here we listen to the changes that occurred on that button internally (Say when it was clicked what happened to the class) and we use that change to do something else, say emit a particular color.

Example

Think of the scenario that you would like to make a favorite icon on a component, now you know that you would have to know whether the item has been Favorited with its class changed, we need a way to determine this. That is exactly where @Hostbinding comes in.

And where there is the need to know what action actually was performed by the user that is where @Hostlistening comes in

Raphael Amponsah
  • 549
  • 6
  • 13
5

METHOD DECORATORS:

@HostBinding: Dynamic binding custom logic to Host element

 @HostBinding('class.active')
 activeClass = false;

@HostListen: To Listen to events on Host element

@HostListener('click')
 activeFunction(){
    this.activeClass = !this.activeClass;
 }

Host Element:

  <button type='button' class="btn btn-primary btn-sm" appHost>Host</button>
rohit.khurmi095
  • 2,203
  • 1
  • 14
  • 12