Angular is a popular front-end framework made by Google. Like other popular front-end frameworks, it uses a component-based architecture to structure apps.
In this article, we’ll look at how to create and use attribute directives with Angular.
Build a Simple Attribute Directive
We can create a simple directive by using the Angular CLI.
To create one, we run:
ng generate directive highlight
to create the skeleton code for our directive.
Once we did that, we can write some code for our directive. We write the following code:
highlight.directive.ts
:
import { Directive, ElementRef } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = 'pink';
}
}
The code above takes an ElementRef
of the element that the directive is applied to.
Then we set the backgroundColor
of it to 'pink'
.
The bracket makes our directive an attribute directive.
We should prefix our directive names with something like app
so that they don’t clash with HTML attribute names.
app.module.ts
:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HighlightDirective } from './highlight.directive';
@NgModule({
declarations: [
AppComponent,
HighlightDirective
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
We added HighlightDirective
to our AppModule
so we can use it.
Then we can use it in app.component.html
as follows:
<div appHighlight>foo</div>
We then should see a pink div with ‘foo’ inside it.
Respond to User-Initiated Events
We can also use directives to detect and act on user-initialed events.
For example, we can write the change the HighlightDirective
we had above as follows:
import { Directive, ElementRef, HostListener } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(private el: ElementRef) { }
@HostListener('mouseenter') onMouseEnter() {
this.highlight('pink');
}
@HostListener('mouseleave') onMouseLeave() {
this.highlight(null);
}
private highlight(color: string){
this.el.nativeElement.style.color = color;
}
}
We added the HostListener
decorators to listen to the mouseenter
and mouseleave
events of the element that our highlight
directive is applied to.
Therefore, when we hover over our text, we’ll see it turn pink. Otherwise, it’ll go back to its normal color.
Pass Values Into the Directive with an @Input Data Binding
We can use the @Input
decorator as we do with components to pass data to directives.
For example, we can write the following:
highlight.directive.ts
:
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
@Input() highlightColor: string;
constructor(private el: ElementRef) { }
ngOnInit() {
this.el.nativeElement.style.color = this.highlightColor;
}
}
app.component.html
:
<div appHighlight highlightColor='pink'>foo</div>
In the code above, we added the highlightColor
input and then pass in the color string in app.component.html
to set the color.
We’ll then get pink text since we set highlightColor
to pink.
Bind to an @Input Alias
We can make the code above shorter if we change the @Input
alias to have the same name as the directive name.
For example, we can write:
highlight.directive.ts
:
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
@Input('appHighlight') highlightColor: string;
constructor(private el: ElementRef) { }
ngOnInit() {
this.el.nativeElement.style.color = this.highlightColor;
}
}
Then we can use it as follows in app.component.html
;
<div appHighlight='pink'>foo</div>
As we can see, we don’t have to specify highlightColor
separately anymore.
Bind to a Second Property
We can have multiple @Input
s to bind to multiple properties.
For example, we can write the following:
highlight.directive.ts
:
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
@Input('appHighlight') highlightColor: string;
@Input() defaultColor: string;
constructor(private el: ElementRef) { }
ngOnInit() {
this.el.nativeElement.style.color = this.highlightColor || this.defaultColor;
}
}
In the code above, we have 2 @Inputs
instead of one.
Now we can use it as follows in app.component.html
:
<div appHighlight='pink' defaultColor='yellow'>foo</div>
<div appHighlight defaultColor='green'>bar</div>
In the code above, we have appHighlight
directive applied without any color string set in the second div.
Therefore, since defaultColor
is set to 'green'
, it’ll be applied as we specified in highlight.directive.ts
‘s ngOnInit
method.
Conclusion
We define attribute directives by running ng g directive
and name them with brackets outside the name.
Then we can pass in properties with @Input
s and listen to events with @HostListener
.
Also, we get the element that the directive is applied to and then apply whatever styles we want to it.