` or any other element with the `tooltip` selector,
like so:
```
```
Directives can also control the instantiation, destruction, and positioning of inline template elements:
A directive uses a
ViewContainerRef
to instantiate, insert, move, and destroy views at runtime.
The
ViewContainerRef
is created as a result of `
` element, and represents a location in the current view
where these actions are performed.
Views are always created as children of the current View
, and as siblings of the `` element. Thus a
directive in a child view cannot inject the directive that created it.
Since directives that create views via ViewContainers are common in Angular, and using the full `` element syntax is wordy, Angular
also supports a shorthand notation: `` and `` are equivalent.
Thus,
```
```
Expands in use to:
```
```
Notice that although the shorthand places `*foo="bar"` within the `` element, the binding for the directive
controller is correctly instantiated on the `` element rather than the `` element.
## Example
Let's suppose we want to implement the `unless` behavior, to conditionally include a template.
Here is a simple directive that triggers on an `unless` selector:
```
@Directive({
selector: '[unless]',
properties: {
'unless': 'unless'
}
})
export class Unless {
viewContainer: ViewContainerRef;
protoViewRef: ProtoViewRef;
prevCondition: boolean;
constructor(viewContainer: ViewContainerRef, protoViewRef: ProtoViewRef) {
this.viewContainer = viewContainer;
this.protoViewRef = protoViewRef;
this.prevCondition = null;
}
set unless(newCondition) {
if (newCondition && (isBlank(this.prevCondition) || !this.prevCondition)) {
this.prevCondition = true;
this.viewContainer.clear();
} else if (!newCondition && (isBlank(this.prevCondition) || this.prevCondition)) {
this.prevCondition = false;
this.viewContainer.create(this.protoViewRef);
}
}
}
```
We can then use this `unless` selector in a template:
```
```
Once the directive instantiates the child view, the shorthand notation for the template expands and the result is:
```
```
Note also that although the `` template still exists inside the ``, the instantiated
view occurs on the second `` which is a sibling to the `` element.
.l-main-section
h2 Members
.l-sub-section
h3 constructor
pre.prettyprint
code.
constructor({
selector,
properties,
events,
hostListeners,
hostProperties,
lifecycle,
compileChildren = true,
}:{
selector:string,
properties:any,
events:List,
hostListeners: any,
hostProperties: any,
lifecycle:List,
compileChildren:boolean
}={})
:markdown
.l-sub-section
h3 compileChildren
:markdown
If set to true the compiler does not compile the children of this directive.
.l-sub-section
h3 events
:markdown
Enumerates the set of emitted events.
## Syntax
```
@Component({
events: ['statusChange']
})
class TaskComponent {
statusChange:EventEmitter;
constructor() {
this.statusChange = new EventEmitter();
}
onComplete() {
this.statusChange.next('completed');
}
}
```
.l-sub-section
h3 hasLifecycleHook
pre.prettyprint
code.
hasLifecycleHook(hook:string)
:markdown
Returns true if a directive participates in a given `LifecycleEvent`.
See onChange
, onDestroy
, onAllChangesDone
for details.
.l-sub-section
h3 hostListeners
:markdown
Specifies which DOM hostListeners a directive listens to.
The `hostListeners` property defines a set of `event` to `method` key-value pairs:
- `event1`: the DOM event that the directive listens to.
- `statement`: the statement to execute when the event occurs.
If the evalutation of the statement returns `false`, then `preventDefault`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 following local variables:
- `$event`: Current event object which triggered the event.
- `$target`: The source of the event. This will be either a DOM element or an Angular directive.
(will be implemented in later release)
## Syntax
```
@Directive({
hostListeners: {
'event1': 'onMethod1(arguments)',
'target:event2': 'onMethod2(arguments)',
...
}
}
```
## Basic Event Binding:
Suppose you want to write a directive that triggers on `change` events in the DOM and on `resize` events in window.
You would define the event binding as follows:
```
@Directive({
selector: 'input',
hostListeners: {
'change': 'onChange($event)',
'window:resize': 'onResize($event)'
}
})
class InputDirective {
onChange(event:Event) {
}
onResize(event:Event) {
}
}
```
Here the `onChange` method of `InputDirective` is invoked whenever the DOM element fires the 'change' event.
.l-sub-section
h3 hostProperties
:markdown
Specifies which DOM properties a directives updates.
## Syntax
```
@Directive({
selector: 'input',
hostProperties: {
'value': 'value'
}
})
class InputDirective {
value:string;
}
In this example every time the value property of the decorator changes, Angular will update the value property of
the host element.
```
.l-sub-section
h3 lifecycle
:markdown
Specifies a set of lifecycle hostListeners in which the directive participates.
See onChange
, onDestroy
, onAllChangesDone
for details.
.l-sub-section
h3 properties
:markdown
Enumerates the set of properties that accept data binding for a directive.
The `properties` property defines a set of `directiveProperty` to `bindingProperty`
key-value pairs:
- `directiveProperty` specifies the component property where the value is written.
- `bindingProperty` specifies the DOM property where the value is read from.
You can include a Pipe
when specifying a `bindingProperty` to allow for data transformation and structural
change detection of the value. These pipes will be evaluated in the context of this component.
## Syntax
```
@Directive({
properties: {
'directiveProperty1': 'bindingProperty1',
'directiveProperty2': 'bindingProperty2 | pipe1 | ...',
...
}
}
```
## Basic Property Binding
We can easily build a simple `Tooltip` directive that exposes a `tooltip` property, which can be used in templates
with standard Angular syntax. For example:
```
@Directive({
selector: '[tooltip]',
properties: {
'text': 'tooltip'
}
})
class Tooltip {
set text(text) {
// This will get called every time the 'tooltip' binding changes with the new value.
}
}
```
We can then bind to the `tooltip' property as either an expression (`someExpression`) or as a string literal, as
shown in the HTML template below:
```html
...
...
```
Whenever the `someExpression` expression changes, the `properties` declaration instructs
Angular to update the `Tooltip`'s `text` property.
## Bindings With Pipes
You can also use pipes when writing binding definitions for a directive.
For example, we could write a binding that updates the directive on structural changes, rather than on reference
changes, as normally occurs in change detection.
See Pipe
and keyValDiff
documentation for more details.
```
@Directive({
selector: '[class-set]',
properties: {
'classChanges': 'classSet | keyValDiff'
}
})
class ClassSet {
set classChanges(changes:KeyValueChanges) {
// This will get called every time the `class-set` expressions changes its structure.
}
}
```
The template that this directive is used in may also contain its own pipes. For example:
```html
```
In this case, the two pipes compose as if they were inlined: `someExpression | somePipe | keyValDiff`.
.l-sub-section
h3 selector
:markdown
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 the `sub_selector`.
- `selector1, selector2`: select if either `selector1` or `selector2` matches.
Suppose we have a directive with an `input[type=text]` selector.
And the following HTML:
```html