In this video tutorial, we cover the concept of using structural directives like *ngIf
, *ngFor
, and *ngSwitchCase
in Ionic 2. Structural directives are an Angular concept, but we will be discussing them in the context of an Ionic application. In short, a structural directive allows us to add or remove content to our applications based on some condition.
We will walk through a few basic examples, and also discuss why we use the weird star syntax for structural directives.
Here’s the video:
Video Notes
- Directives preceded with a
*
like*ngIf
,*ngFor
, and*ngSwitchCase
are structural directives - Structural directives modify the DOM by adding or removing certain elements
- If an element is removed, it is completely removed rather than just being hidden. This has performance benefits as Angular no longer has to perform change detection for the element
- The
*
syntax is used as a shortcut for creating template tags - The
*ngIf
structural directive will remove or show an element based on whether the variable it is bound to evaluates totrue
orfalse
- The
*ngFor
structural directive will loop over an array of data and create a DOM element for each element in the array, stamping it with the specific values for each array element (if interpolations are being used) - The
*ngSwitchCase
structural directive will test if the value it is bound to matches the value being switched, and if it matches it will display the element (kind of like having multiple*ngIf
directives, but cleaner)
Video Transcript
In this tutorial, I am going to talk about how structural directives work in Ionic. This is an Angular concept, so it is not specific to Ionic, but we are going to be using an Ionic application as an example here.
0:22
A structural directive is a way to modify the DOM (document object model) – the structure of your web page. They allow us to modify that by removing or adding certain DOM elements. All structural directives have this weird *
syntax in front of them. I am going to talk a little bit about that as well.
0:49
You will see different kinds of structural directives. You will see the *ngIf
that we’re using as a first example here, *ngFor
, and we have this *ngSwitchCase
as well. All each perform slightly different things but each of them are removing or adding content from the DOM as a result of the directive.
src/app/pages/home/home.html
<ion-header>
<ion-navbar>
<ion-title> Structural Directives </ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<div *ngIf="brag">
<h2>I'm awesome!</h2>
</div>
<template [ngIf]="brag">
<div>
<h2>I'm awesome!</h2>
</div>
</template>
<!--
<div *ngFor="let name of names">
<h2>{{name}} is awesome!</h2>
</div>
-->
<!--
<div [ngSwitch]="whoIsAwesome">
<h2> *ngSwitchCase="'Jennifer'">Jennifer is awesome!</h2>
<h2> *ngSwitchCase="'Waleed'">Waleed is awesome!</h2>
<h2> *ngSwitchCase="'Michael'">Michael is awesome!</h2>
</div>
-->
</ion-content>
*ngIf
1:09
This first example we are going to look at is *ngIf
. That handles the displaying a certain element or not displaying an element. The important difference with *ngIf
is if that condition is not met then the element itself is actually removed from the document, it is not just hidden. The difference here is that we could just hide it with CSS or something and still have it there, we just can’t see it. The difference is that by removing it completely there are some performance benefits because Angular no longer has to perform change detection on that, it’s not consuming more resources because it is completely gone. It may not always be the best thing to do depending on what the goals are for your application, but generally, it is going to be a better idea to remove an element with *ngIf
rather than just hiding it if a certain condition is met.
2:10
In the first example here, we are using the *ngIf
and we are linking it to this ‘brag’ variable that I have already defined in the home.ts file.
src/app/pages/home/home.ts
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
brag: boolean = false;
names: any = true;
whoIsAwesome: any = 'Jennifer';
constructor(public navCtrl: NavController) {
this.name = ['Jennifer', 'Waleed', 'Michael'];
}
}
2:20
Right now I have just got a boolean and I have that set to false. The idea is that with *ngIf
we are saying if the brag condition is met then show whatever is inside of the <h2>
container. In this case, it is set to false
so it is not going to display anything.
2:38
I wanted to talk a little bit about specifically this *
syntax and why we use that. The short of it is that it is just to make writing these structural directives easier. The code I have underneath the *ngIf
is exactly the same thing. The [ngIf]
will display the <h2>
tag if the brag variable is set to true just in the same way as the *ngFor
will. So, these two are exactly the same except the *ngFor
is using this shortcut syntax *
to create this for us.
3:12
What you can see here is that this *
syntax is creating a template. This is an HTML5 tag and in a normal application what happens with these template tags is, by default, they are hidden when they are added to the DOM. What Angular does, is it treats these as a bit of a special case. It will remove any templates it finds and replaces it with its own script tag which it is then going to use to perform whatever things it needs to do. In the case of an *ngIf
, it is either going to hide or display something. In the case of *ngFor
, it is going to loop over a bunch of data and display it.
3:55
We need to create these template tags but it is a bit of work to create a template tag, assign this ngIf
directive to it, and put everything we need inside of that template. Instead, we use the *ngIf
syntax which will handle creating the template automatically for us.
4:13
If we take a look at what is happening in the browser now, you will see that it is completely blank right now because the boolean was set to false. So, this condition isn’t being met so it is not being displayed. If I head over to the home.ts file and I change the boolean to true and take a look in the browser, you can see that both of the <h2>
tags are being rendered out now.
export class HomePage {
brag: boolean = true;
names: any = true;
whoIsAwesome: any = 'Jennifer';
constructor(public navCtrl: NavController) {
this.name = ['Jennifer', 'Waleed', 'Michael'];
}
4:45
As I mentioned, *ngIf
and [ngIf]
do exactly the same thing, when the ‘brag’ variable is set to true it is going to render out ‘I’m awesome’ which is why we see both of those being output to the screen.
*ngFor
4:48
Now, let’s move on to the *ngFor
directive. This is a similar approach where we are using this *
syntax but instead of hiding or showing an element based on some condition, with this one we are able to loop over an array of data.
src/app/pages/home/home.html
<ion-header>
<ion-navbar>
<ion-title> Structural Directives </ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<div *ngIf="brag">
<h2>I'm awesome!</h2>
</div>
<template [ngIf]="brag">
<div>
<h2>I'm awesome!</h2>
</div>
</template>
<div *ngFor="let name of names">
<h2>{{name}} is awesome!</h2>
</div>
<!--
<div [ngSwitch]="whoIsAwesome">
<h2> *ngSwitchCase="'Jennifer'">Jennifer is awesome!</h2>
<h2> *ngSwitchCase="'Waleed'">Waleed is awesome!</h2>
<h2> *ngSwitchCase="'Michael'">Michael is awesome!</h2>
</div>
-->
</ion-content>
5:18
In the home.ts file I have just got an array defines 3 names: Jennifer, Waleed and Michael. What this allows us to do is loop over these and inject each of them as their own element into the DOM. This is going to inject the <h2>
for each of the names we have and then it is going to use this interpolation {{name}}
to add that specific name to the <h2>
tag.
5:44
If I were to save this now, we should see the 3 names rendered out in the browser and you can see all of those names there.
*ngSwitch
5:52
As a final example, we have this *ngSwitch
which checks a certain variable and then tests it for different values. What I have set us now is I am looking at this “whoIsAwesome” variable. Right now I have it set to Jennifer in the home.ts file.
src/app/pages/home/home.html
<ion-header>
<ion-navbar>
<ion-title> Structural Directives </ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<div *ngIf="brag">
<h2>I'm awesome!</h2>
</div>
<template [ngIf]="brag">
<div>
<h2>I'm awesome!</h2>
</div>
</template>
<div *ngFor="let name of names">
<h2>{{name}} is awesome!</h2>
</div>
<div [ngSwitch]="whoIsAwesome">
<h2>*ngSwitchCase="'Jennifer'">Jennifer is awesome!</h2>
<h2>*ngSwitchCase="'Waleed'">Waleed is awesome!</h2>
<h2>*ngSwitchCase="'Michael'">Michael is awesome!</h2>
</div>
</ion-content>
6:11
It is going to create these template tags for us automatically, we don’t have to worry about that, we just have to use this *
syntax. What is going to happen is it is going to test for each of these values. It is saying that in the case that the value equals Jennifer – and also make a note that we have added these quotations (“Jennifer”) because this is a string value we are looking for – it is going to test the value equals Jennifer and if it does it is going to render out that Jennifer is awesome. It is going to get rid of these other two names.
6:45
If I save that now, because it is set to Jennifer in the home.ts file, that is what we should see in the app here and we do.
6:54
That was just a really quick example of how to use structural directives in Ionic and in Angular applications. I mainly wanted to go over the concept of templates and what this *
syntax is doing. Of course, there are more complicated things you can do with structural directives but hopefully, that gives you the basic idea of what is going on behind the sense rather than just wondering why we put this random star in front of things.
7:24
I hope you enjoyed this tutorial and I will see you in the next one.