Directives - deependhamecha/angular GitHub Wiki
<div appDude="red"></div>
@Input('appDude') appDude: string;
<input type="text" [formControl]="someFormControl" myCustomDirective />
constructor(
private el: ElementRef,
private control: NgControl
) {}
ngOnInit() {
const abstractControl = this.control.control;
abstractControl && abstractControl.setValidators([Validators.required]);
}
@Input() set unless(condition: boolean) {
if(!condition) {
this.vcRef.createEmbeddedView(this.templateRef);
} else {
this.vcRef.clear();
}
}
constructor(private templateRef: TemplateRef<any>, private vcRef: ViewContainerRef) { }
Directive has only OnInit and OnDestroy lifecycle because it does not have view.
@Directive({
selector: 'appDude', // [appDude] OR .appDude
})
import { Directive, ElementRef, OnInit } from '@angular/core';
// Attribute Directive
@Directive({
selector: '[appMyDirective]'
})
export class MydirectiveDirective implements OnInit {
constructor(private elementRef: ElementRef) {}
ngOnInit() {
// This aint a good practice, check BetterHightlight directive
this.elementRef.nativeElement.style.backgroundColor = 'green';
this.elementRef.nativeElement.style.color = 'white';
this.elementRef.nativeElement.style.padding = '10px';
}
}
If you need to link events on which directive is used, eg: MouseEnter/MouseLeave on a paragraph.
<p appDude></p>
@HostListener('mouseenter')
mouseOver(eventdata: Event) {}
@HostListener('mouseleave')
mouseLeft(eventdata: Event) {}
import { Directive, Input, OnChanges } from '@angular/core';
@Directive({
selector: '[insBtn]',
host: {
'[class.btn]': '_shouldBe',
'[class.btn-primary]': '_shouldBe'
},
inputs: ['bankName', 'branch: building']
})
export class InsbtnDirective implements OnChanges {
constructor() { }
_shouldBe: boolean;
get shouldBe() {
return this._shouldBe;
}
@Input('shouldBe')
set shouldBe(value: boolean) {
console.log(value);
this._shouldBe = value;
}
// @Input('shouldBe') _shouldBe: boolean;
bankName: string;
branch: string;
ngOnChanges(simple) {
console.log(simple);
}
}
<button type="button" insBtn [shouldBe]="shouldBe">Ins Btn</button>
shouldBe: boolean=true;
It work for direct @Input('shouldBe') _shouldBe: boolean
because host only looks at instance variables of the component and not the input.
<p *ngIf="booleanValue; else otherValue">Dude</p>
<ng-template #otherValue>
<p>Display this instead.</p>
</ng-template>
There are two types of directives:
- Non structural - Does not add a template
- Structural - Adds a template
It creates a <!-- template binding -->
place holder in html when you check dev tools with value.
ngIf
unlike ng-hide
in angularjs removes the element from the DOM.
<p *ngIf="booleanValue">Show this on true</p>
When you write structural directive(*), it adds a <ng-template>
.
<p *ngIf="condition">Our heroes are true!</p>
<ng-template [ngIf]="condition">
<p>
Our heroes are true!
</p>
</ng-template>
<p [ngIf]="condition">
Our heroes are true!
</p>
import { Directive, Renderer2, HostListener, ElementRef } from '@angular/core';
@Directive({
selector: '[appHostlistenerDirective]'
})
export class HostlistenerDirectiveDirective implements OnInit {
constructor(private el: ElementRef, private renderer: Renderer2) {
console.log('jjj')
}
ngOnInit() {
this.renderer.setStyle(this.el.nativeElement, 'background-color', 'yellow');
}
@HostListener("mouseenter")
mouseEnter(event: Event) {
this.renderer.setStyle(this.el.nativeElement, 'text-shadow', '1px 1px 5px black');
}
@HostListener('mouseleave')
mouseLeave(event: Event) {
this.renderer.setStyle(this.el.nativeElement, 'text-shadow', 'none');
}
}
- If you dont use the directive, it wont be instantiated(constructor wont be called).
-
@HostListener
listens to event. -
ElementRef
gives reference to the element on which directive is applied. -
Renderer2
is used for dynamic styling. <div appHostlistenerDirective></div>
If you want even better hold on styling then use HostBinding
@HostBinding('style.textShadow') textShadow = 'none';
@HostListener("mouseenter")
mouseEnter(event: Event) {
// this.renderer.setStyle(this.el.nativeElement, 'text-shadow', '1px 1px 5px black');
this.textShadow = '1px 1px 5px black';
}
@HostListener('mouseleave')
mouseLeave(event: Event) {
// this.renderer.setStyle(this.el.nativeElement, 'text-shadow', 'none');
this.textShadow = 'none';
}
If you want input parameters, then use @Input
to access inside directive.
<div appMyDirective [color]="red"></div>
@Input() color: string;
@HostBinding('style.color') mycolor = this.color;
If you have certain situation where you have different value for component input and directive input then you can do like this
<app-com [appMyDirective]="'red'"></app-com>
Inside appMyDirective
@Input('appMyDirective') color: string;