Red Green Repeat Adventures of a Spec Driven Junkie

Learning Angular - Directives: ngIf

The next step I am taking in learning Angular: understanding structural directive: ngIf.

I will cover how ngIf differs from using ngStyle under the hood in the inspector. I also go through how Angular keeps track of ngIf in the DOM using ng-reflect-ng-if by walking through an interactive example and displaying changes in the inspector.

Learning how ngIf works gives another tool to conditionally display items in the page and modifying the DOM.

This article will take about four minutes to read.

Jacob Halder - Armor Garniture of George Clifford source and more information

Following Along

If you would like to follow along with this code, you can use the Github link to get a final copy of the code or view the project in your browser using this StackBlitz link.

Introduction

From last article, using ngStyle can make items invisible on a page.

The template code:

<img [ngStyle]="showDog"
     src="https://www.dropbox.com/s/ugeqlxvawfqwhth/dog_by_roaming_angel.jpeg?raw=1">

<p>
  Picture of a dog should appear above when "dog" is typed into the
  field.
</p>

The component code:

export class AppComponent {
    showDog = { 'visibility': 'hidden' }
}

When digging through the page through the browser’s inspector, this shows up:

<img _ngcontent-axr-c0="" src="https://www.dropbox.com/s/ugeqlxvawfqwhth/dog_by_roaming_angel.jpeg?raw=1" ng-reflect-ng-style="[object Object]" style="visibility: hidden;">

Double clicking on hidden and changing the value to visible automatically reveals the image!

Depending on the use case, this can be fine or it cannot be.

In situations where hidden items are still discover-able through the HTML source, using ngStyle won’t help you. ngStyle modifies attributes in the DOM. The item is there, only set to hidden. ngStyle is an attribute directive, a directive that modifies DOM attributes.

To make the item harder to discover, Angular has structural directives , that modify the structure of the DOM so only things that should be there are there.

Directive: ngIf

Let’s start with ngIf - it’s a directive that modifies the structure of the DOM based on a boolean condition. When the boolean condition is true, the DOM element will appear. When the condition is false, the DOM element will not appear.

Using ngIf

ngIf’s format is:

<tag *ngIf="boolean statement">
</tag>

An example template that uses ngIf:

<p *ngIf="true">
  Display if ngIf is true
</p>

<p *ngIf="false">
  Do not appear in the DOM
</p>

ngIf test

When inspecting the HTML source, the element shows:

<!--bindings={
  "ng-reflect-ng-if": "true"
}-->
<p _ngcontent-uld-c0=""> Display if ngIf is true
</p>
<!--bindings={
  "ng-reflect-ng-if": "false"
}-->

As *ngIf="false", Angular doesn’t display the paragraph: Do not appear in the DOM, even in the inspector. This is a way to hide elements, even in the HTML source.

How does ngIf work?

For ngIf to work, Angular needs to keep track of where to insert the element when the condition is true, it includes special elements:

<!--bindings={
  "ng-reflect-ng-if": "true"
}-->

<!--bindings={
  "ng-reflect-ng-if": "false"
}-->

To keep track of where in the DOM these elements should be if the state changes.

Interactive Testing Out

Let’s modify the program from a previous version, adding an input box that will display an image when the word matches:

<p *ngIf="show_ngIf">
  Display if ngIf is typed in
</p>
<br>
<input (keyup)="imageCheck($event)"><br>

and the associated component code:

export class AppComponent {
    show_ngIf = false;
    imageCheck(event: any) {
        let input_string = event.target.value;

        this.show_ngIf = /.*ngIf.*/.test(input_string);
    }
}

When you type ngIf in the input field, show the “Display if ngIf is typed in” paragraph.

ngIf display

Let’s see what is happening in the inspector when the input changes:

ngIf display with inspector

When show_ngIf changes from false to true, Angular makes structural changes to the DOM, inserting the appropriate element at the ng-reflect-ng-if tag!

Combining together

Let’s modify the code to show the dog image when entering dog in the input field and hide it when dog is not entered.

<p *ngIf="show_ngIf">
  Display if ngIf is typed in
</p>

<img *ngIf="show_dog"
  src="https://www.dropbox.com/s/ugeqlxvawfqwhth/dog_by_roaming_angel.jpeg?raw=1">

<br>
<input (keyup)="imageCheck($event)"><br>

The associated component code:

export class AppComponent {
    show_ngIf = false;
    show_dog = false;
    imageCheck(event: any) {
        let input_string = event.target.value;

        this.show_ngIf = /.*ngIf.*/.test(input_string);
        this.show_dog = /.*dog.*/.test(input_string);
    }
}

The result:

ngIf with dog picture

and what’s going on in the inspector:

ngIf with dog picture and inspector

ngIf is magical~!

Conclusion

When an element needs appear on the page after a certain condition, even in the source, using a structural directive such as ngIf will make that happen.

Angular has special hooks to maintain where in the DOM the ngIf should modify using ng-reflect-ng-if elements, that’s part of the Angular magic.