Feel free to skip the detailed steps and jump directly to the stackblitz demo at the end of the post
@HostBinding lets you set properties on the host element or component.
Steps to be followed
-
As a good practice, create a separate directory to place all your custom directives in your angular project. I have a created a new folder name
directives
under thesrc/app
directory -
Create a new file
border.directive.ts
inside thedirectives
directory -
In the
border.directive.ts
file, create a usual typescript class just as below.
export class BorderDirective { }
-
To make this class as a attribute directive, we need to decorate it with
@Directive
annotation
@Directive() export class BorderDirective { }
-
We must give this directive a name using the
selector
property just as we do for a @Component. The name we give here will be used in the html files.
@Directive({ selector: '[border]' }) export class BorderDirective { }
In the above step, if you notice, we have surronded the name with
[]
because this directive will be an attribute directive. But in case of@Component
we don't surround the selector with brackets because they will be used as tags< >
in the html templates.-
By this point, you might notice an error for
@Directive
. To fix that, add the import statement as the first line in the file.
import { Directive } from '@angular/core';
-
To use this new custom directive we have to declare it in our module
app.module.ts
.
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { AppComponent } from './app.component'; import { BorderDirective } from './directives/border.directive.ts'; @NgModule({ imports: [ BrowserModule, FormsModule ], declarations: [ AppComponent, BorderDirective ], bootstrap: [ AppComponent ] }) export class AppModule { }
-
That's it! Our new custom directive is ready to be added to any DOM element or component. Let's add this to a
<div>
tag in ourapp.component.html
<div border> This is a simple div with 'border' attribute </div>
If you run the application, you won't see any border around the
div
. Because we didn't specify anything in ourborder.directive.ts
whenborder
attribute is found on a DOM element.-
To do that, lets add the below snippet to our
BorderDirective
class in theborder.directive.ts
file
@HostBinding('style.borderStyle') get style() { return 'solid'; }
@HostBinding
decorator binds the property specified in the argument to the host DOM element. In the above snippet, we binded the border-style property to the host element.-
You might notice an error for
@HostBinding
, to fix that add the required import.
import { Directive, HostBinding } from '@angular/core';
-
Now if you run the application, you will find a solid border around the div. Yay!!
But if you notice, we are not done yet. Because, the style is border is same and not configurable. So we must provide a way to the consumer(i.e., div or any DOM element) to provide the styles they want.
-
So let's add an input property in the
BorderDirective
class and update the style() method as below. If the consumer doesn't provide the bStyle attribute, then it will be defaulted to 'solid'.
@Directive({ selector: '[border]' }) export class BorderDirective { @Input() bStyle: string = 'solid'; @HostBinding('style.borderStyle') get style() { return this.bStyle; } }
-
Don't forget to add the import for
@Input
.
import { Directive, HostBinding, Input } from '@angular/core';
-
Now add another div to our html file as below and verify the output
<div border> This is just a div with border directive </div> <div border bStyle='dotted'> This is just a div with border directive and specifies the style using the bStyle property </div>
-
Similarly we can add and customize various properties for the border.
import { Directive, HostBinding, Input } from '@angular/core'; @Directive({ selector: '[border]' }) export class BorderDirective { @Input() bStyle: string = 'solid'; @Input() bRadius: number = 10; @Input() bPadding: number = 10; @Input() bMargin: number = 10; @Input() bColor: string = 'lightgrey'; @Input() bWidth: number = 2; @HostBinding('style.borderStyle') get style() { return this.bStyle; } @HostBinding('style.borderRadius') get radius() { return `${this.bRadius}px`; } @HostBinding('style.padding') get padding() { return `${this.bPadding}px`; } @HostBinding('style.margin') get margin() { return `${this.bMargin}px`; } @HostBinding('style.borderColor') get color() { return this.bColor; } @HostBinding('style.borderWidth') get thickness() { return `${this.bWidth}px`; } }
Stackblitz Demo
Top comments (0)