Angular:How I understood @HostBinding in Directives

Angular&NodeEnthusiast
Geek Culture
Published in
6 min readNov 14, 2021

I have always found @HostBinding and Renderer2 as 2 good ways to manipulate the DOM in Angular without directly accessing it. But @HostBinding, in some cases does a better job by keeping the code clean and making it more readable.

@HostBinding can manipulate the properties,attributes and classes of a DOM element.

I would like to share 3 simple examples that helped me understand how @HostBinding can be really useful.

I. Toggling a class

You would have come across this scenario where a class C needs to be added to an element when an Event A occurs and then remove the same class C when an Event B occurs.

<p appTest>Hello World</p>

Above is just a paragraph tag with some text. We have applied a TestDirective to this tag.

Below is the class that we wish to toggle. This class will add a red solid border around the <p> tag.

.box1 {
width: auto;
height: auto;
border: 1px solid red;
}

This is what we want to achieve:

  1. Initially the box1 class should not be applied to the <p> tag.
  2. When the mouse hovers over the <p> tag, box1 class must be applied.
  3. When the mouse moves away from the <p> tag, the box1 class must be removed.
export class TestDirective {@HostBinding('class.box1') toggle: boolean = false;constructor() {}
@HostListener(‘mouseleave’)
@HostListener(‘mouseover’)
onMouseOver() {
this.toggle = !this.toggle;
}
}

As you can see below,We are accessing the box1 class on the <p> tag as ‘class.box1’.

@HostBinding('class.box1') toggle: boolean = false;

The value of the variable toggle decides whether the box1 class will be applied to the <p> tag or not. Since its initial value is false, the box1 class wont be applied to the <p> tag.

This completes step-1.

When the mouse hovers over the text, the class must be added i.e toggle must be true and when the mouse leaves the text, the class must be removed i.e toggle must be false.

Thus the value of toggle needs to keep switching between true and false. The below piece of code achieves that. We have used @HostListener to listen for DOM events. Whenever there is mouseover or a mouseleave event, the onMouseOver() is called. In this method we keep switching the values of toggle between true and false to add and remove the class respectively.

This completes step-2 and step-3.

@HostListener(‘mouseleave’)
@HostListener(‘mouseover’)
onMouseOver() {
this.toggle = !this.toggle;
}

II. Toggling between 2 classes and setting the style of an element

In this example, we will try to toggle between 2 classes and try to set the background color of the element.

<p appTest2>Good Morning</p>

This is again a paragraph tag with some text. We have applied the Test2 Directive to this <p> tag.

Below are the 2 classes we wish to toggle between. span1 class will change the color of text of the <p> tag to red and span2 class will change the color of text to yellow

.span1 {color: red;}.span2 {color: yellow;}

This is what we want to achieve:

  1. <p> tag will initially have span1 class added to it i.e color of text will be red. Initially its background color must be yellow.
  2. On clicking on the <p> tag text, span1 class must be removed and span2 class must be added. i.e color of text must be yellow. On subsequent clicks, the span1 and span2 classes must keep toggling.
  3. When the mouse hovers over the <p> tag, the background color of the tag must change from the initial yellow to green.
  4. When the mouse leaves the <p> tag, the background color of the tag must change from green to brown.
export class Test2Directive {@HostBinding(‘class.span1’) span1: boolean = true;
@HostBinding(‘class.span2’) span2: boolean = false;
@HostBinding(‘style.backgroundColor’) bgColor: string = ‘yellow’;
constructor() {}@HostListener(‘click’)
onClick() {
this.span1 = !this.span1;
this.span2 = !this.span2;
}
@HostListener(‘mouseover’)
onMouseAction() {
this.bgColor = ‘green’;
}
@HostListener(‘mouseleave’)
onMouseLeave() {
this.bgColor = ‘brown’;
}
}

This is how we have accessed the 2 classes span1, span2 and the backgroundColor property of the style attribute using @HostBinding.

@HostBinding(‘class.span1’) span1: boolean = true;
@HostBinding(‘class.span2’) span2: boolean = false;
@HostBinding(‘style.backgroundColor’) bgColor: string = ‘yellow’;

Since variable span1 is set to true, it implies the span1 class will be initially applied to the <p> tag.

Since variable span2 is set to false, it implies the span2 class wont be applied to the <p> tag.

The bgColor variable controls the background color applied to the <p> tag. It will be initially yellow.

This completes step-1.

@HostListener(‘click’)
onClick() {
this.span1 = !this.span1;
this.span2 = !this.span2;
}

On clicking on the <p> tag, we want to remove the span1 class i.e span1 must be set to false and add span2 class i.e span2 must be set to true. On subsequent clicks again, the classes must toggle. As you can see above the onClick() achieves this purpose.

This completes step-2.

@HostListener(‘mouseover’)
onMouseAction() {
this.bgColor = ‘green’;
}
@HostListener(‘mouseleave’)
onMouseLeave() {
this.bgColor = ‘brown’;
}

On mouse hover and mouse leave, we want the background colors to switch. Since the bgColor variable controls the background color of the <p> tag. All we need to do is set this variable to the desired color when the event occurs.

The above methods onMouseAction() and onMouseLeave() acheives this.

This completes step-3 and step-4.

III. Accessing and changing the attributes of DOM elements.

In this example, I have taken an <input> tag and set its maxlength and minlength attributes via @HostBinding. We shall display a message when the <input> tag value’s length is either less than the set minlength or when it equals the maxlength set.

<input appProp (action)=”handleAction($event)” type=”text”
[(ngModel)]=”boxData”/>
<p>{{ message }}</p>

We have applied the PropDirective to the <input> tag.

Component Class:

The class is quite straightforward and self-explanatory.

public boxData: any = ‘’;
public message: string;
handleAction(evt) {
this.message = evt;
}

Now lets get to the Directive.

export class PropDirective {@Output(‘action’) action = new EventEmitter<any>();
@HostBinding(‘attr.maxlength’) max: number = 10;
@HostBinding(‘attr.minlength’) min: number = 3;
constructor() {}@HostListener(‘keyup’, [‘$event.target.value’])
onTyping(data: any) {
if (data.length < this.min) {
this.action.emit(`Enter atleast ${this.min} character`);
} else if (data.length >= this.min && data.length < this.max) {
this.action.emit(‘’);
} else {
this.action.emit(`Reached max char limit of ${this.max} characters`);
}
}
}

This is how we have accessed the maxlength and minlength attributes of the <input> tag. We have set them to 10 and 3 respectively.

@HostBinding(‘attr.maxlength’) max: number = 10;
@HostBinding(‘attr.minlength’) min: number = 3;

variable max controls the maxlength attribute and variable min controls the minlength attribute.

As the user starts typing the keyup event gets triggered and the onTyping() gets executed.

@HostListener(‘keyup’, [‘$event.target.value’])
onTyping(data: any) {
if (data.length < this.min) {
this.action.emit(`Enter atleast ${this.min} character`);
} else if (data.length >= this.min && data.length < this.max) {
this.action.emit(‘’);
} else {
this.action.emit(`Reached max char limit of ${this.max} characters`);
}
}

Here we are first checking if the <input> tag value’s length is less than min i.e 3. If yes, we emit an @Output type event with the below message to the component:

this.action.emit(`Enter atleast ${this.min} character`);
Data length less than 3 (min)

If the <input> tag value’s length is greater than or equal to min i.e 3 but less than max i.e 10, we send back an empty string to the component:

this.action.emit(‘’);
Data length is atleast 3(min) but less than 10(max). No message displayed

If neither of the above satisfies, it implies the <input> tag value’s length has reached the max i.e 10. In that case the below message is sent back to the component.

this.action.emit(`Reached max char limit of ${this.max} characters`);
Data length equals 10(max)

You can check all the 3 examples in the link below:

--

--

Angular&NodeEnthusiast
Geek Culture

Loves Angular and Node. I wish to target issues that front end developers struggle with the most.