This post is a sequence of the previous directives part 1. In this post, I’ll just explain what each directive does.
ngClass
ngClass directive changes the class
attribute of the element when a value is supplied.
This binding can happen in 3 different ways
- String
- Array
- Object
1. String binding:
No explanation here. This is pretty easy with sample code here.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//our root app component | |
import {Component} from '@angular/core' | |
@Component({ | |
selector: 'my-app', | |
template: ` | |
<div> | |
<p ngClass="text-center">ngClass string binding here</p> | |
</div> | |
`, | |
styles: [ | |
` | |
.text-center{ | |
text-align: center; | |
} | |
` | |
] | |
}) | |
export class App { | |
constructor() { | |
} | |
} |
Not a lot of magic here. We’ve just added our CSS class in the styles and accessed with ngClass directive here. Binding with static class name won’t bring much of the advantage of ngClass directive, it is better to use normal class
attribute in this case.
2. Array binding
In this case, we’ll just assign the ngClass
to an array of CSS class names. It’s the same code again but just a change in the assignment.
Example:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<p [ngClass]="['text-center', 'bold-text']">string binding here</p> |
text-center
and bold-text
are our CSS classes available and we bind those classes to have our template reflect styles.
3. Object binding
In this Object binding, we’ll assign ngClass with an object containing of keys (which are CSS classes) and values of those classes as true/false. So, if a property is true, then the CSS class will be applied and if it’s false it won’t apply that class name to the tag.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Component({ | |
selector: 'my-app', | |
template: ` | |
<div> | |
<p [ngClass]="{ 'text-center': true, color: true }">ngClass string binding here</p> | |
</div> | |
`, | |
styles: [ | |
` | |
.text-center{ | |
text-align: center; | |
} | |
.bold-text { | |
font-weight: bold; | |
} | |
.color { | |
color: red; | |
} | |
` | |
] | |
}) |
Notice how I used text-color
in the object. If the CSS class contains hypens or any special characters wrap it in single quotes.
ngStyle
ngStyle is similar to style
property in CSS. Unlike normal style attribute for HTML elements, ngStyle
will have object literal syntax. This object can be passed from the component dynamically or can be hardcoded within the object as well.
Example:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div [ngStyle]="{'color': 'red', 'font-weight': 'bold'}">content</div> |
If the styles are dynamic then we can just pass the object to ngStyle from the component export and it will apply the styles.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Component } from '@angular/core'; | |
@Component({ | |
selector: 'my-app', | |
template: ` | |
<div> | |
<h2 [ngStyle]="styles">Hello {{name}}</h2> | |
</div> | |
`, | |
}) | |
export class App { | |
name:string; | |
border = '2px solid green'; | |
styles = { | |
'color': 'red', | |
'font-weight': 'bold', | |
'border': this.border | |
}; | |
constructor() { | |
this.name = `Angular! v${VERSION.full}` | |
} | |
} |
In the above code observe the border property. We can still have our dynamic properties added to that object literal.
Attribute directive (revisited)
Recollect the example of attribute directive that we used in part 1 of the directives.
We’ll just extend the functionality of that colorMe directive. Let’s add some events to the directive using HostListener decorator.
Host Listener, listens to the events on the directive that we’ve created.
Use case: We’ll just add click and double click events to the directive. On single click, we’ll apply red color to the target element and on double click we’ll apply green color to it.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Directive, ElementRef, HostListener } from '@angular/core' | |
@Directive({ | |
selector: '[colorMe]' | |
}) | |
export class ColorDirective{ | |
constructor(private el: ElementRef){ | |
el.nativeElement.style.color = 'gray'; | |
} | |
@HostListener('click') onClick() { | |
this.el.nativeElement.style.color = 'red'; | |
} | |
@HostListener('dblclick') onDblClick() { | |
this.el.nativeElement.style.color = 'green'; | |
} | |
} |
As you can see the default color of our directive will be gray and when you click on the text it tuns into ‘red’ and if you double click on the text then it tuns ‘green’.
Demo of directive using Host Listener
Structural directives:
ngIf, ngFor and ngSwitch are the built-in structural directives provided by angular.
ngIf:
ngIf
is pretty simple. It takes a boolean expression and will hide/show the DOM element with respective to the boolean expression.
Example:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<p *ngIf="visible">visible element</p> | |
<p *ngIf="!visible">visible element</p> |
The above example is a just a toggle between two elements using visible
as an expression for ngIf. The second p
tag is not actually visible in the DOM. Why?
Note: when the expression inside of ngIf is false, angular will remove that element from DOM, detatches events, detaches from component change detection and destroys the element.
ngSwitch:
ngSwitch is similar to JavaScript switch
statement except the syntax of Angular.
Example:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<container-element [ngSwitch]="switch_expression"> | |
<some-element *ngSwitchCase="match_expression_1">…</some-element> | |
<some-element *ngSwitchCase="match_expression_2">…</some-element> | |
<some-other-element *ngSwitchCase="match_expression_3">…</some-other-element> | |
<some-element *ngSwitchDefault>…</some-element> | |
</container-element> |
the ngSwitch
is the switch
keyword in javascript. ngSwitchCase
is case
statement in switch and ngSwitchDefault
is the default
option in switch case.
ngFor/ngForOf:
ngFor is a like for loop in JavaScript but with different syntax of angular.
Example:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div *ngFor="let item of groceries; let i=index;"> | |
({{i}}) {{item.name}} | |
</div> |
We will iterate through items in the list or object and print them or use them to supply arguments to other child elements.
ngFor is a selector of ngForOf directive. But we need both these directive to be present on an element to display it.
Why is it? See the source code. Check the selector in the source code. FYI here is the selector mentioned in the source.
@Directive({selector: ‘[ngFor][ngForOf]‘})
Though we don’t write ngForOf angular will generate by itself when we use *ngFor. *ngFor is not actually what the compiler sees it. When we use *ngFor, then angular compiler de-sugars into cannonical form which has both the attributes on the element.
The cannonical form:
Asterisk is the syntactic sugar for translating to template syntax.
So, if we have *ngFor code as
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div *ngFor="let item of groceries; let i=index;"> | |
({{i}}) {{item.name}} | |
</div> |
then it is translated to
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div template="ngFor let item of groceries" let-i="index"> | |
({{i}}) {{item.name}} | |
</div> |
In the translated code we don’t have *(asterisk’s) anymore. The above code is again de-sugared into template syntax.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template ngFor let-item [ngForOf]="groceries" let-i="index"> | |
({{i}}) {{item.name}} | |
</template> |
Now, in the final template syntax we have both ngFor and ngForOf keywords within the template. ngFor is just a marker here and ngForOf is an input to the directive that points list of items. This process of translating the string to template syntax is called Microsyntax.
More on microsyntax.