Directives
January 30, 2024About 3 min
Directives
- A
directive
is essentially afunction
that executes whenever the Angular compiler finds it in theTemplate
Directives
are used to extend the power of theHTML
by adding newsyntax
- A
component
is therefore a (more advanced)directive
Example
- The following
StackBlitz
example contains the most commondirectives
:
Structural directives
Structural directives
are used to manipulate the DOM- They shape or reshape the DOM's structure, typically by adding, removing, or manipulating elements
- Easy recognizable by the asterisk (
*
) prefix
structural directive | example | purpose |
---|---|---|
@if | @if(showFirstDiv) { ... } | Takes a boolean expression and makes an entire chunk of the DOM appear or disappear (NOT hidden) |
@else | @else { ... } | If the boolean expression returns false we add a the HTML within the else block |
@for | @for (n of names; track $index) { ... } | Adds the element(s) within the @for n-times to the DOM based on the amount of items in the list. The block of HTML acts as a template for rendering each item in the list |
@for (n of names; track $index; let i = $index,isFirst = $first, isLast = $last) { ... } | Values we can use as local variables withing the @for : index, count, first, last, even, odd |
@if: why removing instead of hiding?
- When the boolean expression in the
@if
directive
returns false, the entire element is removed from the DOM - Hiding the element would mean that all the
bindings
andevents
still exist, although the element is invisible - This requires extra (unnecessary) resources from Angular (and thus the browser), which could slow down the application
@for aliases
- Within the
@for
directive we can access somevalues
which could be interesting to know because we are working with aniteration
- These
values
can be aliased to local variableslet i = $index;
:index
is thevalue
,i
is thelocal variable
let isFirst = $first
:first
is thevalue
,isFirst
is thelocal variable
- ...
@for : track $index
Track is a feature that helps Angular identify unique items in a collection, allowing it to track changes more efficiently and re-render only the elements that have been modified.
Track really comes into play when looping more complex objects, but we just add it by default right now!
Attribute directives
Attribute directives
listen to and modify the behavior of otherHTML elements
,attributes
,properties
, andcomponents
@switch
- The
@switch
directive is actually a set of cooperating directives:switch
,case
, anddefault
<div>
@switch (color) {
@case ('green') {
<div class="green">GREEN</div>
}
@case ('red') {
<div class="red">RED</div>
}
@case ('blue') {
<div class="blue">BLUE</div>
}
@default{
<div class="gray">DEFAULT</div>
}
}
</div>
@switch
accepts aproperty
or aexpression
@case
checks its value against the@switch
value and returns the HTML when they are a match
single quotes in an expression
- There is a difference when using single quotes or not in an
expression
@case('green')
:expression
is just the stringgreen
@case(green)
:expression
is the propertygreen
[ngClass]
- Add or remove several CSS classes simultaneously
- Based on a
boolean property
:isSpecial
<div [ngClass]="isSpecial ? 'special' : ''">This div is special</div>
- Based on an
object
ofclasses
:currentClasses
<div [ngClass]="currentClasses">Current classes div</div>
Component
class file
isSpecial: boolean = true;
currentClasses: {};
isLarge: boolean = true;
isError: boolean = false;
setCurrentClasses() {
// CSS classes based on business logic
this.currentClasses = {
large: this.isLarge,
error: this.isError
};
}
CSS
.special {
border: 2px dotted red;
}
.large {
font-size: 2rem;
}
.error {
color: red;
background-color: rgba(255, 0, 0, 0.1);
}
Add/remove single class
- To add or remove a single class, use
class binding
rather thanNgClass
[class.sale]="onSale"
: addssale
class to element ifonSale
expression
is true
[ngStyle]
- Set many inline styles simultaneously and dynamically, based on the state of the component
<div [ngStyle]="currentStyles">Current styles div</div>
currentStyles: {};
isItalic: boolean = true;
isBold: boolean = false;
setCurrentStyles() {
// CSS inline styles based on business logic
this.currentStyles = {
"font-style": this.isItalic ? "italic" : "normal",
"font-weight": this.isBold ? "bold" : "normal"
};
}
A component is a directive
- A
component
is adirective
- This makes perfect sense because a
component
is loaded when defining theselector
as an HTML element in thetemplate
- We are extending the power of the
HTML
, because we add a complete new set of elements to the DOM
- We are extending the power of the
- Therefore a
component
is adirective
with atemplate
Want proof? Check the source code!
- Go to the
node_module\@angular\core\index.d.ts
file and check thedeclaration
of theComponent interface
(line 1436):
/**
* Supplies configuration metadata for an Angular component.
*
* @publicApi
*/
export declare interface Component extends Directive {
/**
* The change-detection strategy to use for this component.
*
* When a component is instantiated, Angular creates a change detector,
* which is responsible for propagating the component's bindings.
* The strategy is one of:
* - `ChangeDetectionStrategy#OnPush` sets the strategy to `CheckOnce` (on demand).
* - `ChangeDetectionStrategy#Default` sets the strategy to `CheckAlways`.
*/
changeDetection?: ChangeDetectionStrategy;
...
- The
Component interface
extends adirective interface
Check it yourself
- Check the news app and find out where we already implemented some of these
directives
Exercise
Building on the stackblitz above implement the following features.
- Add a checkbox that binds to the showSecondDiv property so you can change this
- Create a dropdown that binds to the color property with options "green" and "blue"