Angular Directives Tutorial
In this Angular tutorial we learn how Angular sends instructions to the DOM with its built-in Directives.
We cover the ngIf and ngFor structural directives as well as the ngStyle and ngClass attribute directives.
What are Directives
Simply put, Directves are instructions in the DOM.
For example, once we place the selector of our component, we are instructing Angular to add the content of our component in its place.
Directives use the @Directive decorator. There are 3 types of directives in Angular.
- Component Directives, which are used in the main class of a component. They contain the information of how that component is processed, instantiated and used.
- Attribute Directives, which are used to change the style and behavior of DOM elements. Angular has some built-in structural directives like ngClass and ngStyle.
- Structural Directives, which are used to change and manipulate the structure of DOM elements. Structural directives are prefixed with an * operator. Angular has some built-in structural directives like *ngIf and *ngFor .
We can also create our own custom directives .
Let’s take a look at a few of Angular’s built-in directives.
Lesson project setup
For this lesson there is no initial setup other than having an app.
To keep things simple, we will be working directly from inside the main ‘app.component’ component and will create whatever else we need on a step-by-step basis.
The ngIf Structural Directive
The ngIf directive allows us to conditionally add, or not add, something to the DOM. It works similar to a regular if statement.
We use it on the element we want to add, as an attribute selector. Because ngIf is a structural directive, we must prefix it with the * operator.
<element *ngIf="expression">The element we want to add</element>
We can use any expression that evaluates to either true or false .
For example, let’s say we have special menu items that we only want to show to users that are logged in.
In the component’s class we can create a boolean variable that indicates whether or not the user is logged in.
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
isLoggedIn:boolean = false;
}
The ngIf directive will be able to evaluate this variable and add, or not add, the menu item based on the evaluation being true or false.
This value can come from an external source like a database but we’ll hard-code it here for demonstration.
In the component’s view we add the variable as the ngIf directive’s expression.
The expression reads: if isLoggedIn == true add this <li>
<ul>
<li>Menu item for all users</li>
<li>Menu item for all users</li>
<li *ngIf="isLoggedIn">Menu item for logged in users only</li>
</ul>
If we check the webpage, we’ll see that the menu item doesn’t show because isLoggedIn is false.
If we go ahead change it to true in the class and check the webpage again, Angular will add the menu item to the DOM and we can see it on the page.
The ngIf with else
Angular allows us to specify an else condition for our ngIf directive.
The else condition is used with a local reference and is separated from the if expression with a ; operator.
<element *ngIf="expression; else localReference">The element we want to add</element>
A local reference is like a marker we can add to the ng-template directive. The ng-template directive comes bundled with Angular and is used to mark places in the DOM.
<ng-template #localReference>
html code here
<ng-template>
Our local reference must be prefixed with a # operator.
For example, let’s say we want to show a logged in user an extra menu item like in the previous section, and a message when they’re not logged in.
But, we don’t want to show this message in the menu, we want it to be somewhere else on the page.
The class will stay the same. It just contains the boolean variable isLoggedIn that we evaluate in the ngIf expression.
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
isLoggedIn:boolean = false;
}
In the view, we add an ng-template with a local reference called #notLoggedIn . This contains the message we want to show if the user is not logged in, and the extra menu item is not displayed.
The local reference name can be anything we want except for reserved keywords.
In the ngIf we add an else statement with our local reference name.
The statement now reads: if isLoggedIn == true add this <li>, otherwise add whatever is in #notLoggedIn
<ul>
<li>Menu item for all users</li>
<li>Menu item for all users</li>
<li *ngIf="isLoggedIn; else notLoggedIn">Menu item for logged in users only</li>
</ul>
<ng-template #notLoggedIn>
<p>You are not logged in</p>
</ng-template>
If we take a look at the webpage, we will see the notLoggedIn message is displayed in the paragraph below the menu, where we placed the reference.
Changing the isLoggedIn variable to true will remove the message and show the menu item.
The ngFor Structural Directive
Angular allows us to loop through elements with a for of loop by using the ngFor structural directive.
<element *ngFor="let tempItem of List">
// use {{ tempItem }}
</element>
As an example, let’s say we want to display a list of our favorite films on the page.
1. First, we will need to create an array or list of values in the component’s class, or pull them from an external source like a database.
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
topFilms = [
'The Godfather',
'Star Wars: Episode V',
'The Dark Knight',
'Pulp Fiction',
'Back to the future',
'Alien',
'Fight Club',
'Die Hard',
'Jurassic Park',
'Inception'
];
}
We chose an array of string values to keep the demonstration simple.
2. Next, we create the for of loop expression as the value for the ngFor directive where we want to display the list in the component’s view.
The expression will consist of the following:
- A temporary variable that will hold the specific iteration’s value. In our case the temporary variable name is film .
- Then we specify of which array or list it must iterate through. In our case it’s the topFilms array we defined in the component class.
- Lastly, we use the film temporary variable with data binding inside the element we want the value to display in.
We only specify this loop once. When it executes, it will insert all the list items based on the values in the array.
<h3>Top 10 films of all time</h3>
<ul>
<li *ngFor="let film of topFilms">{{ film }}</li>
</ul>
If we run the example in the browser, we get the full list of films in unordered list format.
We can also get the number of each element by creating another temporary variable and assigning the array’s index number to it with the index keyword.
<element *ngFor="let tempItem of List; let tempIndexNum = index">
// use {{ tempIndexNum }} and/or {{ tempItem }}
</element>
If we have multiple expressions in a directive, we separate them with the semicolon operator.
For example, let’s say we want to add numbers to our top 10 films list.
<h3>Top 10 films of all time</h3>
<ul>
<li *ngFor="let film of topFilms; let i = index">{{ i }}. {{ film }}</li>
</ul>
If we take a look at the app in the browser, all the films will have their corresponding index numbers.
Of course, arrays start at zero so the first film on our list will show as 0. This may not be what we want, so let’s change it by simply adding 1 to the number where we display it.
Angular allows us to perform simple mathematical calulations directly inside a property binding.
<h3>Top 10 films of all time</h3>
<ul>
<li *ngFor="let film of topFilms; let i = index">{{ i+1 }}. {{ film }}</li>
</ul>
If we run the example in the browser, it will now show the list starting at number 1.
It’s important to note that the change is made where we display the value with property binding. It doesn’t affect the array in the component class.
The ngStyle Attribute Directive
Attribute directives look just like normal HTML attributes. They don’t add elements to the DOM like structural directives, instead they only change what’s already there.
One of these attribute directives is ngStyle , which allows us to change the CSS styling of elements dynamically.
Attribute directives are written differently than structural directives. Let’s see the syntax.
<element [ngStyle]="{ 'css-property': 'value' }">
</element>
We aren’t allowed to write ngStyle on its own, it needs a configuration to do something. That’s why we use property binding on it by wrapping it in square brackets.
It’s important to understand that the square brackets aren’t part of the directive name. They simply indicate that we want to bind to a property on this directive, and that this property name also happens to be ngStyle.
We are binding to a property, called ‘ngStyle’, that is of the directive called ngStyle .
As the directive value, we define a Javascript object with the CSS property name(s) and value(s) we want to change as key:value pairs. Or, we can use Javascript’s camelCase notation.
<element [ngStyle]="{ cssProperty: 'value' }">
</element>
If we use camelCase notation, we don’t have to wrap the property name in quotes.
You can use whichever notation you feel most comfortable with, just remember to stay consistent. We will use the regular CSS notation throughout this course.
As example, let’s create a simple paragraph in our main component’s view and change its styling.
<p [ngStyle]="{
'background-color': '#232323',
'color': '#fafafa',
'padding': '.8rem'
}">Lorem ipsum dolor</p>
In the example above we change the background and text color, as well as give the paragraph some padding all around.
But, let’s say that we want to change the styling conditionally. For example, if a user is online, we want their username to show as a green color.
First, let’s specify a method that will return the desired color as the value for the color CSS property.
<p [ngStyle]="{ 'color': isOnlineColor() }">Username</p>
The isOnlineColor() method will calculate the color based on some condition and return the correct one.
So let’s create it in the component’s class.
We will simulate that the user is online with a boolean variable called ‘isOnline’. Then, we simply check if it’s true or false and return a color based on the result.
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
isOnline = true;
isOnlineColor() {
if(this.isOnline) {
return 'green';
} else {
return 'gray';
}
}
}
When we run the example in the browser, the paragraph should be green.
The ngClass Attribute Directive
The ngClass attribute directive also allows us to change the View’s styling dynamically. It does this by adding or removing CSS classes based on conditions.
Like with the ngStyle directive, we use property binding and a Javascript object.
The Javascript object wants a key:value pair where the key is the class name we want to add and the value is the condition.
<element [ngClass]="{ 'css-class-name': condition }">
</element>
As an example, let’s do the same thing we did in the ngStyle section and turn a username green when the user is online.
1. First, we’ll add the class to our component’s CSS.
.online {
color: green
}
When the user is online, Angular will add this class to the paragraph the username is written in, and turn it green.
2. We will use the isOnline boolean variable in the condition. If you don’t already have it from the previous section, add it in the component class.
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
isOnline = true;
}
The condition will check if this value is true or false and add or remove the class from the paragraph element.
3. Finally, let’s add the directive in the View of the component.
<p [ngClass]="{ 'online': isOnline }">Username</p>
Let’s take a look at the key:value pair in the object.
- ‘online’ is the class we want to add when the condition evaluates to true.
- isOnline is the condition. Because it’s a boolean we can simply write its name to do a true check. It’s the same as writing isOnline === true
At first glance it seems as though using ngClass is a more complicated way of doing what we did with ngStyle , but it’s not.
It’s also better practice to separate our CSS and HTML code as much as possible.