128 lines
3.2 KiB
Markdown
128 lines
3.2 KiB
Markdown
# Directives
|
|
|
|
## Attribute vs Structural directives
|
|
|
|
<img src="../img/attribute_structural_directives.png" alt="attribute_structural_directives" width="800"/>
|
|
|
|
## Create basic attribute directives
|
|
|
|
Namingconvention: `name.directive.ts`
|
|
|
|
Generate it with the CLI:
|
|
```bash
|
|
ng generate directive <name>
|
|
|
|
# short:
|
|
ng g d <name>
|
|
```
|
|
|
|
<img src="../img/basic_directive.png" alt="basic_directive" width="550"/>
|
|
|
|
In `app.modules.ts` has to be added under `declarations` and *import* the source path to the directive.
|
|
|
|
Use it in the template.html with just adding the name `appBasicHighlight` to the component.
|
|
|
|
## Using Renderer for attribute directives
|
|
|
|
<img src="../img/renderer.png" alt="renderer" width="700"/>
|
|
|
|
Renderer is a better approach to accessing the DOM. Why? Because Angular dont works only in the Browser, but also with worker, which maight in certain circumstances will get errors.
|
|
|
|
## HostListener
|
|
|
|
With HostListener is a neat way to style the Element based on certain events triggered from the host (mouseover, mouseenter, mouseleave, etc).
|
|
|
|
<img src="../img/reactive_directive.png" alt="renderer" width="800"/>
|
|
|
|
## HostBinding
|
|
|
|
with HostBinding is the renderer no longer needed and is much simpler to change an elements backgroundcolor.
|
|
```ts
|
|
@Directive({
|
|
selector: '[appBetterHighlight]'
|
|
})
|
|
export class BetterHighlightDirective implements OnInit {
|
|
@HostBinding('style.backgroundColor') backgroundColor: string = 'transparent';
|
|
|
|
ngOnInit() {
|
|
}
|
|
|
|
@HostListener('mouseenter') mouseover(eventData: Event) {
|
|
this.backgroundColor = this.highlightColor;
|
|
}
|
|
|
|
@HostListener('mouseleave') mouseleave(eventData: Event) {
|
|
this.backgroundColor = this.defaultColor;
|
|
}
|
|
}
|
|
```
|
|
|
|
## Binding to directive properties
|
|
|
|
The hardcoded colors can be set from the outside using the `@Input` like so
|
|
|
|
```html
|
|
<p appBetterHighlight [defaultColor]="'yellow'" [highlightColor]="'blue'">bliblubla</p>
|
|
```
|
|
|
|
```ts
|
|
import {
|
|
Directive,
|
|
Renderer2,
|
|
OnInit,
|
|
ElementRef,
|
|
HostListener,
|
|
HostBinding,
|
|
Input
|
|
} from '@angular/core';
|
|
|
|
@Directive({
|
|
selector: '[appBetterHighlight]'
|
|
})
|
|
export class BetterHighlightDirective implements OnInit {
|
|
@Input() defaultColor: string = 'transparent';
|
|
@Input('appBetterHighlight') highlightColor: string = 'blue';
|
|
@HostBinding('style.backgroundColor') backgroundColor: string;
|
|
|
|
ngOnInit() {
|
|
this.backgroundColor = this.defaultColor;
|
|
}
|
|
|
|
@HostListener('mouseenter') mouseover(eventData: Event) {
|
|
this.backgroundColor = this.highlightColor;
|
|
}
|
|
|
|
@HostListener('mouseleave') mouseleave(eventData: Event) {
|
|
this.backgroundColor = this.defaultColor;
|
|
}
|
|
|
|
}
|
|
```
|
|
|
|
## Building a structural directive
|
|
|
|
```ts
|
|
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
|
|
|
|
@Directive({
|
|
selector: '[appUnless]'
|
|
})
|
|
export class UnlessDirective {
|
|
@Input() set appUnless(condition: boolean) {
|
|
if (!condition) {
|
|
this.vcRef.createEmbeddedView(this.templateRef);
|
|
} else {
|
|
this.vcRef.clear();
|
|
}
|
|
}
|
|
|
|
constructor(private templateRef: TemplateRef<any>, private vcRef: ViewContainerRef) { }
|
|
|
|
}
|
|
```
|
|
|
|
## ngSwitch
|
|
|
|
<img src="../img/ngSwitch.png" alt="ngSwitch" width="400"/>
|
|
|
|
ngSwitch can be used for replacing a lot of ngIf statements. |