20 June 2019
Angular (7) -- Directives
by Jerry Zhang
Day 16:
JavaScript setInterval
```javascript 1.8 onStart() { this.interval = setInterval(() => { this.timeNow = this.timeNow + 1; this.started.emit(this.timeNow); }, 1000); }
This anonymous function will be executed every one second. The `setInterval()` function is assigned to a reference
`this.interval`. With this reference, later on, we can pause this interval using the code below.
```javascript 1.8
onPause() {
clearInterval(this.interval);
}
Also notice that we used an ES6 syntax () => { }
.
Create our own attribute directive
Create a new file called basic-highlight.directive.ts
.
import {Directive, ElementRef, OnInit} from '@angular/core';
@Directive({
selector: '[appBasicHighlight]'
})
export class BasicHighlightDirective implements OnInit{
constructor(private elementRef: ElementRef) {
}
ngOnInit() {
this.elementRef.nativeElement.style.backgroundColor = 'green';
}
}
@Directive tells Angular this is a directive. The only mandatory attribute it needs is a selector, because this is
the way we can use the new directive. Here, we defined it as [appBasicHighlight]
. This must be unique.
Also remember that when we define a custom directive, we must notify Angular in the app.module.ts
file by adding it
to the declarations
array.
import {BasicHighlightDirective} from './basic-highlight/basic-highlight.directive';
@NgModule({
declarations:
BasicHighlightDirective
],
imports: [
BrowserModule,
FormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Then we can use it in the html file.
<p appBasicHighlight>Style me with basic directive!</p>
A better way
import {Directive, ElementRef, OnInit, Renderer2} from '@angular/core';
@Directive({
selector: '[appBetterHighlight]'
})
export class BetterHighlightDirective implements OnInit {
constructor(private elRef: ElementRef, private renderer: Renderer2) { }
ngOnInit(): void {
this.renderer.setStyle(this.elRef.nativeElement, 'background-color', 'blue');
}
}
If you want to listen to some events in the directive, you can use HostListener.
@Directive({
selector: '[appBetterHighlight]'
})
export class BetterHighlightDirective implements OnInit {
constructor(private elRef: ElementRef, private renderer: Renderer2) { }
ngOnInit(): void {
// this.renderer.setStyle(this.elRef.nativeElement, 'background-color', 'blue');
}
@HostListener('mouseenter') mouseover(eventData: Event) {
this.renderer.setStyle(this.elRef.nativeElement, 'background-color', 'blue');
}
@HostListener('mouseleave') mouseleave(eventData: Event) {
this.renderer.setStyle(this.elRef.nativeElement, 'background-color', 'transparent');
}
}
Or, we could simply use @HostBinding instead of the renderer.
export class BetterHighlightDirective implements OnInit {
@HostBinding('style.backgroundColor') backgroundColor: string = 'transparent';
constructor(private elRef: ElementRef, private renderer: Renderer2) { }
ngOnInit(): void {
// this.renderer.setStyle(this.elRef.nativeElement, 'background-color', 'blue');
}
@HostListener('mouseenter') mouseenter(eventData: Event) {
// this.renderer.setStyle(this.elRef.nativeElement, 'background-color', 'blue');
this.backgroundColor = 'blue';
}
@HostListener('mouseleave') mouseleave(eventData: Event) {
// this.renderer.setStyle(this.elRef.nativeElement, 'background-color', 'transparent');
this.backgroundColor = 'transparent';
}
}
Tip: mouseover, mouseenter, onmouseover
The mouseover event triggers when the mouse pointer enters the div element, and its child elements.
The mouseenter event is only triggered when the mouse pointer enters the div element.
The onmousemove event triggers every time the mouse pointer is moved over the div element.
Binding to directive properties
Use custom property binding. Then, all the properties can be set dynamically at runtime.
@Directive({
selector: '[appBetterHighlight]'
})
export class BetterHighlightDirective implements OnInit {
@Input() defaultColor = 'transparent';
@Input() highlightColor = 'blue';
@HostBinding('style.backgroundColor') backgroundColor: string;
constructor(private elRef: ElementRef, private renderer: Renderer2) { }
ngOnInit(): void {
this.backgroundColor = this.defaultColor;
// this.renderer.setStyle(this.elRef.nativeElement, 'background-color', 'blue');
}
@HostListener('mouseenter') mouseenter(eventData: Event) {
// this.renderer.setStyle(this.elRef.nativeElement, 'background-color', 'blue');
this.backgroundColor = this.highlightColor;
}
@HostListener('mouseleave') mouseleave(eventData: Event) {
// this.renderer.setStyle(this.elRef.nativeElement, 'background-color', 'transparent');
this.backgroundColor = this.defaultColor;
}
}
Change it from outside.
<p appBetterHighlight [defaultColor]="'yellow'" [highlightColor]="'red'">Style me with a better directive!</p>
Binding a main property for a directive
We can set an alias for a property in the directive, with the same name as its selector. Then, we put a square
bracket around this directive, similar to [ngClass]
.
@Input('appBetterHighlight') highlightColor = 'blue';
<p [appBetterHighlight] = "'red'" [defaultColor]="'yellow'">Style me with a better directive!</p>
A shortcut when passing down a string
We can remove the quotation mark and the square brackets.
<p [appBetterHighlight] = "'red'" defaultColor="yellow">Style me with a better directive!</p>
Behind the star symbol of structural directives
Using
<ng-template [ngIf]="!onlyOdd">
<div>
<li
class="list-group-item"
[ngClass]="{odd: even % 2 !== 0}"
*ngFor="let even of evenNumber">
</li>
</div>
</ng-template>
tags: Angular