Angular directives plays a major role in an angular application. So we say, Components are the building blocks of an Angular application, but you know Component is actually a directive. Basically a directive is a function that executes whenever the angular compiler finds it in the DOM.
All the directives have their own respective names like ng-repeat or some custom names. So angular divides these directives into three types such as,
- Components
- Attribute directive
- Structural directive
Components
As we saw in previous blogs, angular is streamlined on component-based architecture.
All the components are defined with @Component decorator. Basically these components are just directives with their own templates.
But behind the scenes they use directive API’s and it’s very easy to define an component in Angular.
app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular';
}
It is a directive which has templates. The other two directives doesn’t have a template instead they are strongly dependent on DOM manipulation.
Attribute directive
Attribute directives are used to apply conditional styles to HTML elements or changing the behavior of the component dynamically based upon a property etc. Basically it just manipulates the DOM based upon a condition.
So let us a see a small example of how we can create this attribute directive. In this example we are going to create an highlighter directive which highlights a text when you mouse hover on it.
highlight.directive.ts
import { Directive, ElementRef,
HostListener, Input } from '@angular/core';
@Directive({
selector: '[appHighlight]'
//we have to use this selector to access this directive
})
export class HighlightDirective {
constructor(private el: ElementRef) { }
@Input('appHighlight') highlightColor: string;
@HostListener('mouseenter') onMouseEnter() {
this.highlight(this.highlightColor);
}
@HostListener('mouseleave') onMouseLeave() {
this.highlight(null);
}
private highlight(color: string) {
this.el.nativeElement.style.backgroundColor = color;
}
}
A directive needs to be accessed by it’s selector. Here we have given [appHighlight] as the directive selector name. Basically it receives an input color from the DOM and it changes the attribute of the DOM depends upon the color given to this directive.
In attribute directives, we use ElementRef to manipulate it’s behavior in the DOM.
app.module.ts
import { HighlightDirective } from './highlight.directive';
@NgModule({
declarations: [
HighlightDirective
]
})
export class AppModule { }
If you want to use this directive you need to import this directive in your respective module.
app.component.html
<p [appHighlight]="'red'">Hover on me! Highlight me!</p>
<p [appHighlight]="'green'">
Hover on me! Highlight me too!
</p>
In the above html, we are using this directive in our html as [appHighlight] which will be received by the respective directive using @Input() decorator. So if you hover on it, the respective color will be displayed.
Attribute directive demo => https://bit.ly/387jJpH
Structural directive
Structural directives are used to create and destroy DOM elements. There are many predefined structural directives such as ngIf, hidden, ngClass etc. Basically these directives will change the entire HTML structure and we need to be very careful whenever we are using these structural directives.
Let us see an example of how we can create and use structural directives. In this example, we are going create our own custom IF directive.
myCustomIf.directive.ts
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[myCustomIf]'
//we will use this selector name to access the directive
})
export class MyCustomIfDirective {
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef) { }
@Input() set myCustomIf(condition: boolean) {
if (condition) {
this.viewContainer.createEmbeddedView(this.templateRef);
//if the condition is true create a view
} else {
this.viewContainer.clear();
//otherwise destroy it
}
}
}
We will create and destroy elements in the DOM using templateRef and viewContainer.
app.module.ts
import { MyCustomIfDirective } from './myCustomIf.directive';
@NgModule({
declarations: [ MyCustomIfDirective ]
})
export class AppModule { }
Next we have to import this directive into the respective component module to use it.
app.component.html
<h2 *myCustomIf="condition">Hello {{name}}</h2>
<button (click)="condition = !condition">Click to toggle!</button>
Here we have used the custom structural directive as myCustomIf. It just toggles the DOM and it will render the view for us.
Structural Directive demo => https://bit.ly/38cmm9Z
Conclusion
So which is better? Structural or Attribute directive?
It totally depends on your requirements. Basically if you want to do some styling changes or if you want to get a value from a view then you can go for Attribute directives. If you want to create and destroy elements in the DOM go for Stuctural directives.
Choose the right directive at the right place!
In our next blog, we will see about Angular Interceptors.
Happy Coding!
Cheers! 🙂
Leave a Reply