Directives
Pipes
Class that attaches to an existing DOM element and modifies its appearance, behavior or adjacent elements structure
Uses @Divective decorator
<my-component></my-component>
<div *myDirective></div>
<div myDirective></div>
<div [myDirective]></div>
<div (myDirective)></div>
<div [(myDirective)]></div>
$ ng g directive directives/new-stuff
@NgModule({
declarations: [
AppComponent,
-->NewStuffDirective,
],
imports: [
BrowserModule,
BrowserAnimationsModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
import { Directive } from '@angular/core';
@Directive({
selector: '[appNewStuff]'
})
export class NewStuffDirective {
constructor() { }
}
Designed to modify appearance or behavior of an element
<div myDirective></div>
<div [myDirective]></div>
<div (myDirective)></div>
<div [(myDirective)]></div>
Default dependencies
import { Directive, ElementRef, Renderer2 } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(private elementRef: ElementRef, private renderer2: Renderer2) { }
}
Designed to change the DOM layout by adding or removing DOM elements
<div *myDirective></div>
Angular element for rendering HTML which is never displayed directly
<p>Hip!</p>
<ng-template>
<p>Hip!</p>
</ng-template>
<p>Hooray!</p>
*ngIf
<div *ngIf="hero" class="name">{{hero.name}}</div>
<ng-template [ngIf]="hero">
<div class="name">{{hero.name}}</div>
</ng-template>
else mycrosyntax
<div class="feed" *ngIf="posts; else loading">
...
</div>
<ng-template #loading>
<div>Loading...</div>
</ng-template>
<div [ngSwitch]="hero?.emotion">
<app-happy-hero *ngSwitchCase="'happy'" [hero]="hero"></app-happy-hero>
<app-sad-hero *ngSwitchCase="'sad'" [hero]="hero"></app-sad-hero>
<app-confused-hero *ngSwitchCase="'confused'" [hero]="hero"></app-confused-hero>
<app-unknown-hero *ngSwitchDefault [hero]="hero"></app-unknown-hero>
</div>
<div [ngSwitch]="hero?.emotion">
<ng-template [ngSwitchCase]="'happy'">
<app-happy-hero [hero]="hero"></app-happy-hero>
</ng-template>
<ng-template [ngSwitchCase]="'sad'">
<app-sad-hero [hero]="hero"></app-sad-hero>
</ng-template>
<ng-template [ngSwitchCase]="'confused'">
<app-confused-hero [hero]="hero"></app-confused-hero>
</ng-template >
<ng-template ngSwitchDefault>
<app-unknown-hero [hero]="hero"></app-unknown-hero>
</ng-template>
</div>
<div *ngFor="let hero of heroes; let i=index; let odd=odd">
({{i}}) {{hero.name}}
</div>
<ng-template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd">
<div>({{i}}) {{hero.name}}</div>
</ng-template>
let [template input variable] of [array]; let myVariable = [variable]
Variable | Meaning |
---|---|
index | Index of current element (number, starts 0) |
first | Is element first (boolean) |
last | Is element last (boolean) |
even | Is element even (boolean) |
odd | Is element odd (boolean) |
Custom UnlessDirective example
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
/**
* Add the template content to the DOM unless the condition is true.
*/
@Directive({ selector: '[appUnless]'})
export class UnlessDirective {
private hasView = false;
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef) { }
@Input() set appUnless(condition: boolean) {
if (!condition && !this.hasView) {
this.viewContainer.createEmbeddedView(this.templateRef);
this.hasView = true;
} else if (condition && this.hasView) {
this.viewContainer.clear();
this.hasView = false;
}
}
}
<p *appUnless="condition" class="unless a">
(A) This paragraph is displayed because the condition is false.
</p>
<p *appUnless="!condition" class="unless b">
(B) Although the condition is true,
this paragraph is displayed because appUnless is set to false.
</p>
Custom UnlessDirective example
Class that allow changing data inside of a template
Uses @Pipe decorator
const now = new Date();
function formatDate(date) {
const month = date.getMonth() + 1;
return `${date.getDate()}.${month < 10 ? '0' : ''}${month}.${date.getFullYear()}`
}
{{ now | date: 'dd.MM.yyyy' }}
JavaScript
Angular
$ ng g pipe pipes/filter-by
@NgModule({
imports: [ BrowserModule ],
declarations: [
-->FilterByPipe,
],
bootstrap: [ AppComponent ]
})
export class AppModule{ }
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'myCustomPipe'
})
export class FilterByPipe<T> implements PipeTransform {
transform(items: T[], param1: string, param2: string){
// ...
}
}
<p>{{ expression | pipeName:param1:param2 }}</p>
General syntax
Chaining pipes
<p>{{ 'Angular' | slice:3 | uppercase }}</p>
Angular -> ular -> ULAR
import { AgePipe } from './pipes/custom.pipe';
import { DatePipe } from '@angular/common';
@Component({
selector: 'my-app',
templateUrl: '../app/app.html',
providers: [AgePipe, DatePipe],
})
export class AppComponent implements OnInit {
public currentDay = this.datePipe.transform(new Date(), 'yyyy/MM/dd');
public employees: Employee[];
private allEmployees = employees; // data stored somewhere
constructor(private datePipe: DatePipe, private agePipe: AgePipe) {}
public ngOnInit(): void {
this.employees = this.agePipe.transform(employees, 30);
}
}
Pure Pipes Angular executes a pure pipe only when it detects a pure change to the input value.
Pure pipe
A pure change is either a change to a primitive input value (String, Number, Boolean, Symbol) or a changed object reference (Date, Array, Function, Object).
Pipes are pure by default.
Angular executes an impure pipe during every component change detection cycle.
Impure pipe
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'myCustomPipe',
-->pure: false
})
export class FilterByPipe<T> implements PipeTransform {
transform(items: T[], param1: string, param2: string){
// ...
}
}
An impure pipe will be called a lot, as often as every keystroke or mouse-move.
https://angular.io/api/core/Directive
https://angular.io/guide/attribute-directives
https://angular.io/guide/structural-directives
https://angular.io/api/core/Pipe
https://angular.io/guide/pipes
https://angular.io/guide/cheatsheet
https://github.com/pavelrazuvalau/angular-lectures/tree/master/angular-directives-pipes