Outline
Attribute directives are surrounded by brackets which signals to Angular that the appearance or behavior of the DOM elements within the directive may change depending on certain conditions.
For example:
<h1>My First Attribute Directive</h1>
<h4>Pick a highlight color</h4>
<div>
<input type="radio" name="colors" (click)="color='lightgreen'" />Green
<input type="radio" name="colors" (click)="color='yellow'" />Yellow
<input type="radio" name="colors" (click)="color='cyan'" />Cyan
</div>
<p [appHighlight]="color">Highlight me!</p>
In this template, we have an appHighlight
attribute directive that is bound to the color
property. When a user clicks on the radio buttons, Angular sets the value of color
to the values shown in the template.
Here's the code for the attribute directive:
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(private el: ElementRef) { }
@Input('appHighlight') highlightColor: string;
@HostListener('mouseenter') onMouseEnter() {
this.highlight(this.highlightColor || 'red');
}
@HostListener('mouseleave') onMouseLeave() {
this.highlight(null);
}
private highlight(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
}
You can view the entire sample and explanation on the Angular Docs
Let's take a look at how to create another directive. In this example, we'll be making an attribute directive that bolds text when it is hovered over.
app/bold-hover.directive.ts
import { Directive, ElementRef } from '@angular/core';
@Directive()
export class BoldHoverDirective {
private element: HTMLElement;
constructor(elementRef: ElementRef){
this.element = elementRef.nativeElement;
}
}
ElementRef
provides us with a way of getting a reference to the DOM element
that the directive is attatched to using the nativeElement
property. We're
saving a reference to the element in a private variable called element
.
Directive
is the decorator used for configuring directives, which we'll be
using in the next steps. Just like with configuring components, we'll need to
define a selector
which will tell Angular how to identify the directive that
needs to be used. We can also provide a host
object for binding events from
that elements to functions on our directive
Next we'll configure the selector
and host
properties for our @Directive()
decorator:
import { Directive, ElementRef, HostListener } from '@angular/core';
@Directive({
selector: '[boldHover]'
})
export class BoldHoverDirective {
private element: HTMLElement;
constructor(element: ElementRef){
this.element = element.nativeElement;
}
}
Now our directive can be used in templates by adding boldHover
as an element
attribute like <p boldHover>I turn bold when hovered</p>
Next lets create the onMouseEnter
and onMouseLeave
methods for our directive:
import { Directive, ElementRef } from '@angular/core';
@Directive({
selector: '[boldHover]',
host: {
'(mouseenter)': 'onMouseEnter()',
'(mouseleave)': 'onMouseLeave()'
}
})
export class BoldHoverDirective {
private element: HTMLElement;
constructor(element: ElementRef){
this.element = element.nativeElement;
}
onMouseEnter() {
this.element.style.fontWeight = 'bold';
}
onMouseLeave() {
this.element.style.fontWeight = 'normal';
}
}
Now our directive is ready to be used!
Lets import the directive we made into app/app.component.ts
and register the
directive in the @Component()
decorator.
import { Component } from '@angular/core';
import { BoldHoverDirective } from './bold-hover.directive';
@Component({
selector: 'my-app',
template: '<p boldHover>I turn bold when hovered</p>',
providers: [BoldHoverDirective]
})
export class AppComponent {}
You can view a live demo of this example here:
Now whenever we mouseover the text, it should turn bold!
Challenge: Before proceeding to the next chapter, try creating a structural directive that can display or remove the given element.