linkDirective
npm Package | @angular/core |
---|---|
Module | import { Directive } from '@angular/core'; |
Source | core/src/metadata/directives.ts |
Marks a class as an Angular directive and collects directive configuration metadata.
linkMetadata Overview
@Directive({
selector?: string
inputs?: string[]
outputs?: string[]
host?: {...}
providers?: Provider[]
exportAs?: string
queries?: {...}
})
linkHow To Use
import {Directive} from '@angular/core';
@Directive({
selector: 'my-directive',
})
export class MyDirective {
}
linkDescription
Directive decorator allows you to mark a class as an Angular directive and provide additional metadata that determines how the directive should be processed, instantiated and used at runtime.
Directives allow you to attach behavior to elements in the DOM..
A directive must belong to an NgModule in order for it to be usable
by another directive, component, or application. To specify that a directive is a member of an
NgModule,
you should list it in the declarations
field of that NgModule.
In addition to the metadata configuration specified via the Directive decorator, directives can control their runtime behavior by implementing various Life-Cycle hooks.
Metadata Properties:
- exportAs - name under which the component instance is exported in a template. Can be given a single name or a comma-delimited list of names.
- host - map of class property to host element bindings for events, properties and attributes
- inputs - list of class property names to data-bind as component inputs
- outputs - list of class property names that expose output events that others can subscribe to
- providers - list of providers available to this component and its children
- queries - configure queries that can be injected into the component
- selector - css selector that identifies this component in a template
linkMetadata Properties
selector?: string
The CSS selector that triggers the instantiation of a directive.
Angular only allows directives to trigger on CSS selectors that do not cross element boundaries.
selector
may be declared as one of the following:
element-name
: select by element name..class
: select by class name.[attribute]
: select by attribute name.[attribute=value]
: select by attribute name and value.:not(sub_selector)
: select only if the element does not match thesub_selector
.selector1, selector2
: select if eitherselector1
orselector2
matches.
linkExample
Suppose we have a directive with an input[type=text]
selector.
And the following HTML:
<form>
<input type="text">
<input type="radio">
<form>
The directive would only be instantiated on the <input type="text">
element.
inputs?: string[]
Enumerates the set of data-bound input properties for a directive
Angular automatically updates input properties during change detection.
The inputs
property defines a set of directiveProperty
to bindingProperty
configuration:
directiveProperty
specifies the component property where the value is written.bindingProperty
specifies the DOM property where the value is read from.
When bindingProperty
is not provided, it is assumed to be equal to directiveProperty
.
linkExample (live demo)
The following example creates a component with two data-bound properties.
@Component({
selector: 'bank-account',
inputs: ['bankName', 'id: account-id'],
template: `
Bank Name: {{bankName}}
Account Id: {{id}}
`
})
class BankAccount {
bankName: string;
id: string;
// this property is not bound, and won't be automatically updated by Angular
normalizedBankName: string;
}
@Component({
selector: 'app',
template: `
<bank-account bankName="RBC" account-id="4747"></bank-account>
`
})
class App {}
outputs?: string[]
Enumerates the set of event-bound output properties.
When an output property emits an event, an event handler attached to that event the template is invoked.
The outputs
property defines a set of directiveProperty
to bindingProperty
configuration:
directiveProperty
specifies the component property that emits events.bindingProperty
specifies the DOM property the event handler is attached to.
linkExample (live demo)
@Directive({
selector: 'interval-dir',
outputs: ['everySecond', 'five5Secs: everyFiveSeconds']
})
class IntervalDir {
everySecond = new EventEmitter();
five5Secs = new EventEmitter();
constructor() {
setInterval(() => this.everySecond.emit("event"), 1000);
setInterval(() => this.five5Secs.emit("event"), 5000);
}
}
@Component({
selector: 'app',
template: `
<interval-dir (everySecond)="everySecond()" (everyFiveSeconds)="everyFiveSeconds()">
</interval-dir>
`
})
class App {
everySecond() { console.log('second'); }
everyFiveSeconds() { console.log('five seconds'); }
}
host?: {
[key: string]: string;
}
Specify the events, actions, properties and attributes related to the host element.
linkHost Listeners
Specifies which DOM events a directive listens to via a set of (event)
to method
key-value pairs:
event
: the DOM event that the directive listens to.statement
: the statement to execute when the event occurs. If the evaluation of the statement returnsfalse
, thenpreventDefault
is applied on the DOM event.
To listen to global events, a target must be added to the event name.
The target can be window
, document
or body
.
When writing a directive event binding, you can also refer to the $event local variable.
linkExample (live demo)
The following example declares a directive that attaches a click listener to the button and counts clicks.
@Directive({
selector: 'button[counting]',
host: {
'(click)': 'onClick($event.target)'
}
})
class CountClicks {
numberOfClicks = 0;
onClick(btn) {
console.log("button", btn, "number of clicks:", this.numberOfClicks++);
}
}
@Component({
selector: 'app',
template: `<button counting>Increment</button>`
})
class App {}
linkHost Property Bindings
Specifies which DOM properties a directive updates.
Angular automatically checks host property bindings during change detection. If a binding changes, it will update the host element of the directive.
linkExample (live demo)
The following example creates a directive that sets the valid
and invalid
classes
on the DOM element that has ngModel directive on it.
@Directive({
selector: '[ngModel]',
host: {
'[class.valid]': 'valid',
'[class.invalid]': 'invalid'
}
})
class NgModelStatus {
constructor(public control:NgModel) {}
get valid { return this.control.valid; }
get invalid { return this.control.invalid; }
}
@Component({
selector: 'app',
template: `<input [(ngModel)]="prop">`
})
class App {
prop;
}
linkAttributes
Specifies static attributes that should be propagated to a host element.
linkExample
In this example using my-button
directive (ex.: <div my-button></div>
) on a host element
(here: <div>
) will ensure that this element will get the "button" role.
@Directive({
selector: '[my-button]',
host: {
'role': 'button'
}
})
class MyButton {
}
providers?: Provider[]
Defines the set of injectable objects that are visible to a Directive and its light DOM children.
linkSimple Example
Here is an example of a class that can be injected:
class Greeter {
greet(name:string) {
return 'Hello ' + name + '!';
}
}
@Directive({
selector: 'greet',
providers: [
Greeter
]
})
class HelloWorld {
greeter:Greeter;
constructor(greeter:Greeter) {
this.greeter = greeter;
}
}
exportAs?: string
Defines the name that can be used in the template to assign this directive to a variable.
linkSimple Example
@Directive({
selector: 'child-dir',
exportAs: 'child'
})
class ChildDir {
}
@Component({
selector: 'main',
template: `<child-dir #c="child"></child-dir>`
})
class MainComponent {
}
queries?: {
[key: string]: any;
}
Configures the queries that will be injected into the directive.
Content queries are set before the ngAfterContentInit
callback is called.
View queries are set before the ngAfterViewInit
callback is called.
linkExample
@Component({
selector: 'someDir',
queries: {
contentChildren: new ContentChildren(ChildDirective),
viewChildren: new ViewChildren(ChildDirective)
},
template: '<child-directive></child-directive>'
})
class SomeDir {
contentChildren: QueryList<ChildDirective>,
viewChildren: QueryList<ChildDirective>
ngAfterContentInit() {
// contentChildren is set
}
ngAfterViewInit() {
// viewChildren is set
}
}