DEV Community

Cover image for Angular Structural Directives, Part 1: NgIf
ng-conf
ng-conf

Posted on

Angular Structural Directives, Part 1: NgIf

Michi DeWitt | ng-conf | Oct 2020

This is first part of an ongoing series covering all the built-in Angular structural directives. This series is intended for new and experienced Angular developers.


image

Introduction

Welcome to Part 1 of our series on built-in structural directives in Angular applications! In this series, we are going to cover what structural directives are and provide a guide on how to use each of the built-in structural directives.

What are Structural Directives?

Structural directives allow a developer to manipulate the DOM in specific ways. This manipulation is done by adding, removing, or changing elements on the page. A structural directive is added as an attribute to an HTML element in a template. Only one structural directive can be added to each element and the directive should always be prefixed with an * to make them easy to distinguish from other attributes on the element.

Angular comes with several built-in directives that can be used to control the DOM. Most directives work by manipulating the DOM based on values in the component. They are useful in dynamic applications where the page content often changes based on component values and/or user actions. It can be hard to have dynamic content with vanilla HTML and Javascript, but with Angular’s structural directives, it’s a breeze!

Note: We’ll only be focusing on the built-in directives in this series, but developers can also build their own custom structural directives as well.

How Do I Use Structural Directives?

To make use of a structural directive, the directive is simply added as an attribute on any element in an Angular template. The structural directive attribute is prefixed by the *.

Example:

<div *someDirective class="my-class" (click)="doSomething()"></div>
Enter fullscreen mode Exit fullscreen mode

In the snippet above, the structural directive someDirective is easy to distinguish on the div element because of the * prefix.

A directive may also bind to properties in the component.

Example:

<div *someOtherDirective="someProperty" class="my-class" 
(click)="doSomething()"></div>
Enter fullscreen mode Exit fullscreen mode

In the snippet above, the structural directive someOtherDirective is bound to the component property someProperty.

In this post, we’ll be covering one of the most commonly used directives — ngIf.


What is the NgIf Directive and How is it Used?

The ngIf directive is used to conditionally add or remove elements from the DOM. This is much more powerful than simply showing and hiding elements because you are able to:

  1. Only initialize components when they are needed
  2. Destroy components when they are no longer needed
  3. Not add expensive components when they are not needed

The syntax of the ngIf directive is very similar to a conditional if-statement in Javascript which makes it easy and intuitive for developers to use. (It is also almost identical to the ngIf directive in AngularJS).

Here are some situations this directive is particularly useful for:

  • You want to add/remove content based on the action of a user
  • You want to add/remove content based on some configuration value
  • You want to add/remove content based on one or more values in the component

Basic Usage:

<div *ngIf="someCondition">
  I want to show this if someCondition is truthy!
</div>
Enter fullscreen mode Exit fullscreen mode

The ngIf directive is added as an attribute on any element you want to conditionally add to the DOM. The directive binds to a condition and the value of that condition is used to determine if the element is added or removed.

When the component is first initialized, the value of any ngIf condition is checked and the following will occur:

  • If the condition evaluates to truthy, the element is added to the DOM
  • If the condition evaluates to falsy, the element is not added to the DOM

Simple as that!

If the condition changes as the result of change detection, the element the Angular directive was applied to will be appropriately removed or added to the DOM based on the new conditional value.

Let’s highlight the most important part again because the power of the ngIf directive can be subtle.

When the NgIf condition evaluates to falsy, the element is not hidden in the DOM. It is removed completely — or never added in the first place.

For a small piece of text in a page, this may seem inconsequential. But when combined with more expensive components, you can see large performance implications (both good and bad).

The condition for the ngIf directive can either be bound directly to a property in the component.

Example:

*ngIf="someProperty"
Enter fullscreen mode Exit fullscreen mode

Or the condition can be bound to a boolean expression.

Example:

*ngIf="someProperty !== undefined"
Enter fullscreen mode Exit fullscreen mode

One reason the ngIf directive is easy to use is because it maps closely to the if-statement Javascript syntax many Angular developers are already familiar with. You can mentally map the HTML syntax above to:

if (someCondition) {
  // Execute the code in this block
}
Enter fullscreen mode Exit fullscreen mode

Else Block

Often, you will want to display a different template if the condition in your ngIf directive is falsy. You may be tempted to add a second ngIf directive that explicitly checks if the same condition is falsy

<div *ngIf="someCondition">
  If someCondition is truthy, show this
</div>

<!-- Avoid! This is an anti-pattern. -->
<div *ngIf="!someCondition">
  Otherwise I want to show this
</div>
Enter fullscreen mode Exit fullscreen mode

But there is a better way!

<div *ngIf="someCondition; else otherBlock">
  If someCondition is truthy, show this
</div>

<ng-template #otherBlock>
  Otherwise I want to show this
</ng-template>
Enter fullscreen mode Exit fullscreen mode

Like a traditional if-statement in Javascript, you can specify that a different template should be added in the case the condition in the ngIf directive is falsy.

But why is this better?

  1. First, this provides a clean, easy to understand logical flow in your template.
  2. This keeps your conditional logic in one place. With the anti-pattern shown above, if you change the ngIf condition in one location, you must change it in both. This is brittle and error-prone.
  3. You can add the ng-template anywhere that makes sense in your HTML template. It does not need to be directly underneath the ngIf directive. This gives you more control over how you want to organize your template.

Again, conceptually, this is very similar to the if-else-statement syntax most Angular developers are already familiar with.

f (someCondition) {
  // Execute this code block
} else {
  // Execute this other block
}
Enter fullscreen mode Exit fullscreen mode

Storing NgIf Value

It’s not uncommon to need to use the result of the ngIf condition in multiple places in your template. This is very common when the ngIf condition is bound to an Observable using the async pipe.

One option is to add the condition in the all locations where the result of the ngIf condition is needed…

<div *ngIf="tableData$ | async">
  My Conditional Table
  <my-table-component [data]="tableData$ | async"></my-table-component>
</div>
Enter fullscreen mode Exit fullscreen mode

But again — there’s a better way!

<div *ngIf="tableData$ | async">
  My Conditional Table
  <my-table-component [data]="tableData$ | async"></my-table-component>
</div>
Enter fullscreen mode Exit fullscreen mode

The as syntax allows you to store the result of the condition as a local variable in the template. Now the value is available to easily re-use elsewhere in the template.

But why is this better?

  1. Again, this provides a clean, easy to understand logical flow in your application.
  2. Again, this keeps your conditional logic in one place.
  3. You do not need to create a second subscription to the tableData$ Observable.

Summary

And that’s everything you need to know about the ngIf directive!

Let’s go over the main points again:

🛠 Structural directives provide easy ways for Angular developers to control the DOM based on data in a component

🏗 Structural directives can be added to any element in an Angular template.

🎯 The ngIf directive allows you to control the DOM based on a conditional value you bind directly to the directive

➕ When the ngIf condition is truthy the element will be added to the DOM

➖ When the ngIf condition is falsy the element will be remove from the DOM

💪 Use the else and as syntax to take full advantage of all the features provided by the Angular team

ng-conf: The Musical is coming

ng-conf: The Musical is a two-day conference from the ng-conf folks coming on April 22nd & 23rd, 2021. Check it out at ng-conf.org


Additional Thoughts & Resources

Top comments (0)