The Built-in `NgIf` Directive

Let’s learn about `NgIf`, a built-in attribute directive.

The if statement is probably one of the most recognizable keywords in most programming languages. However, there’s no if statement in HTML.

The ability to complete tasks conditionally is essential for creating dynamic applications. From the front-end perspective, this means the ability to show or hide part of the view. So, the NgIf directive fills this gap and provides an implementation of the if statement for HTML templates.

The NgIf syntax

The structural directive NgIf can be correctly applied to an element by using the * syntax. The asterisk indicates that the directive should be treated as structural one by Angular. We’ll learn more about this syntax later.

NgIf works according to a statement we need to provide. If it’s true, the element is visible on a page. If it’s false, it is hidden.

<div *ngIf="true"> Hello there, I'm visible! </div>

<div *ngIf="false"> and I'm hidden </div>

Let’s check this example:

@Component({
  selector: 'app-user',
  template: `<p *ngIf="signIn">Hello John!</p>`,
})
export class UserComponent implements OnInit {  
	signIn = false;

	constructor(private authService: AuthService){}

	ngOnInit() {
		this.signIn = this.authService.isUserSignIn();
	}
}

In this case, we have a signIn boolean property that takes a true or false value based on the result of the service call. In this scenario, if a user is signed into the application, they’ll see a greeting message and if the user is not authorized, they’ll see nothing.

Let’s go even further. The NgIf directive not only accepts boolean values, but also accepts all valid expressions that might be evaluated as boolean values. So, it accepts almost everything. Therefore, we can pass strings, numbers, enum values, arrays, objects, function calls, and more to NgIf. The NgIf directive evaluates the value of the provided statement, and it shows or hides the element.

With that in mind, we can use more advanced uses of the NgIf directive. For example, because NgIf accepts objects, we can guard against possible null values:

@Component({
  selector: 'app-user',
  template: `<p *ngIf="user">Hello {{ user.name }}!</p>`,
})
export class UserComponent implements OnInit {  
	user;

	constructor(private authService: AuthService){}

	ngOnInit() {
		this.user = this.authService.getUser();
	}
}

Here we can display customized greeting messages but only if the user exists.

That approach has these two advantages:

  • We show the greeting only if the user exists. This is good from a UI point of view.
  • We guard the application against the potential error of accessing undefined values.

How does this protect us from error? Well, we use {{ user.name }}. So, if the user part is undefined or null, we access the property name of the undefined/null value.

The difference between NgIf and other “hiding” features

Using NgIf is the recommended way to show items conditionally in Angular. Why is that? There are many techniques other than NgIf that show items conditionally in Angular. For instance, we can use any of the following:

  • The HTML visibility attribute.
  • The CSS display: none style.
  • Other, more hacky ways, like opacity: 0.

So, why is using NgIf the recommended way to show items conditionally? There’s a significant difference between using NgIf and other methods. The NgIf directive not only hides the element from view, but actually removes it entirely from the DOM. This has very important effects, which are listed below:

  • The DOM is not overloaded with unused elements.
  • All descendants are removed as well.
  • Angular is able to dispose all components from the node.
  • Elements can be removed from the memory and resources.

All these factors can have a massive impact on our performance! In most cases, if we don’t want to show something to the user, we also don’t use it. So, why overload the browser for no reason? Therefore, we should mostly use NgIf and consider alternative techniques only if we have an edge-case solution that has different requirements.

Let’s see this NgIf directive in action! Let’s consider the following components:

Here’s what the main component looks like:

@Component({
  selector: 'app',
  template: `<app-user [name]="name"></app-user>`,
})
export class AppComponent implements OnInit {  
	name = null;

	ngOnInit() {
		setTimeout(() => this.name = 'John', 10000);
		setTimeout(() => this.name = null, 20000);
	}
}

And, here’s the child component:

@Component({
  selector: 'app-user',
  template: `<p>Hello {{ name }}!</p>`,
})
export class UserComponent implements OnInit, OnDestroy {  
	@Input() name;

	ngOnInit() { console.log('🌱 Creating UserComponent') }

	ngOnDestroy() { console.log('💀 Destroying UserComponent') }

}

Now, let’s try these two different approaches:

  • *ngIf
  • opacity: 0

Get hands-on with 1200+ tech skills courses.