What is Angular ngIf & what types of expressions should be used in it?
We are talking about how to prevent an Angular ngIf anti-pattern that we could encounter while creating more complex UI screens that use a lot of data from various sources, like the backend, and stores.
What is Angular ngIf?
This feature, which is added to the language in the form of the unique ngIf attribute, functions as an if statement for HTML.
Eg:
<div class="container" *ngIf="userLoggedIn"> .... visible only to authenticated users <button *ngIf="user.admin">Delete User</button> </div>
In the previous example, the user’s access to see the container div or entire div content depends on whether the user is logged in or not.
There is a button inside the container div that can only be seen by administrators.
What kinds of expressions can you use with Angular ngIf?
The Angular ngIf directive accepts any valid Typescript expression, not only a Boolean, as input. The expression’s veracity will then be assessed in order to determine whether or not the element should be displayed.
In addition to booleans, we will also give objects, strings, arrays, and other data to ngIf. Here are a few examples.
<div class="container-one" *ngIf="0"> .... this content are going to be hidden because 0 is false</div> <div class="container-two" *ngIf="'hello angular'"> .... this content are going to be visible because the string 'hello angular' is truth </div> <div class="container-two" *ngIf="''"> .... this content are going to be hidden because the empty string '' is false </div> <div class="container" *ngIf="{hello: 'world'}"> .... this content are going to be visible because the expression is truth</div> <div class="container-ng" *ngIf="{}"> .... this content also will be visible because the empty object is also truth</div> <div class="container-ngone" *ngIf="[1, 2 ,3,4]"> .... this content are going to be visible because the expression is truth</div> <div class="container-ngtwo" *ngIf="[]"> .... this content are going to be visible because the empty array is also truth </div>
The syntax of the ngIf then else:
The if-then-else syntax is also supported by the ngIf directive in Angular, similarly, we have it available in Javascript or any other language.
Eg:
<ng-container-main *ngIf="courses.length; then coursesList; else noCourses"> </ng-container> <ng-template-list #coursesList> <h1>All courses available</h1> </ng-template> <ng-template-course #noCourses> <h1>No courses available.</h1> </ng-template>
We used an ng-container directive and ngIf in the above-mentioned example. Depending on how accurate the courses are, either one of the two templates, coursesList or noCourses, will be shown. expression of length. The syntax does not support multiple “else if” statements, however, ngSwitch can be used to get the same functionality.
Observable data consumption using ngIf and async pipe:
An Observable may be consumed in the following ways using the angular ngIf directive with async pipe:
<ng-container *ngIf="(courses$ | async) as courses"> <div class="courses"> {{courses.length}} </div> </ng-container>
Courses$ is an Observable emitting object array as values in the example above. This Observable is fetched from the memory.
Async Pipe will subscribe to the Observable and provide the template with access to the values it emits.
We will use ngIf syntax with the “as” syntax in this instance to apply the async pipe. The local template variable for the course makes the values released by the Observable accessible inside the ngIf directive’s scope.
The Observable pattern for just one piece of data:
You may want to refactor your component into the single data observable design because ngIf/async nesting causes concerns with maintainability and user experience.
<ng-container-one *ngIf="(data$ | async) as data"> <div class="header"> ... access the user via data.user </div> <div class="body"> To access the data via data.user, data.courses, data.lessons </div> <div class="footer"> access the data via data.courses and data.lessons </div> </ng-container-one>
We’ll notice that there isn’t any nesting going on, and the ngIf/async combo isn’t used more than once. We only use the async pipe once since we get all the information the template needs to go at the top of the component via a data$ Observable.
What internal processes does Angular ngIf have?
The * syntax indicates that ngIf is a structural directive, which implies it has an impact on the page’s structure.
The template compiler takes the template in its first form when Angular sees the *:
<div class="container" *ngIf="courses.length; else noCourses"> Angular will de-sugar this form of ngIf using the * syntax ... </div> <ng-template #noCourses> <h1>No courses available.</h1>
As we shall see, under the hood the *ngIf directive is actually just a normal Angular attribute that targets the property ngIf.
When a structural directive is applied to an element, the * syntax denotes that the content of that element is considered to be an ng-template and may or may not be included in the page, depending on whether the structural directive decides to instantiate the template or not.
Be aware that this internal de-sugaring process affects all structural directives, not just ngIf, including *ngFor and other directives.
Summary
The Angular ngIf directive functions somewhat similarly to the HTML language’s absent if-then-else capability.
We may effortlessly add or remove things from the webpage by using it and relying on the validity of a Javascript expression.
It’s not like the elements are hidden using CSS when a component is totally deleted from a webpage using ngIf.
When developing web applications in a reactive manner, ngIf is typically used in combination with an async pipe to consume observable data.