Angular – Ejemplo con la directiva ngIf
Una de las principales directivas en angular es la directiva ngIf, que como en cualquier lenguaje funciona como un condicional, es decir, que dependiendo la condición que estemos validando nos ayudara a mostrar uno u otro elemento, solo que al ser un framework para frontend la sintaxis es un poco diferente.
Propiedades de la directiva ngIf
La directiva se comporta como un condicional y existen distintas forma de darle uso, es posible para usar el condicional para mostrar o no un elemento haciendo uso únicamente de la primera condición, podemos definir que en caso que se cumpla la primera condición el contenido a mostrar sea diferente según los distintos valores, esta segunda es preferible integrarla con ngSwitch, así como el @if podemos incorporar un @then o un @else, adicional podemos integrarlo con observadores, así que a continuación veremos algunos ejemplos para cada caso descrito anteriormente.
Ejemplo con condicional simple
En este primer ejemplo mostraremos o no una lista de tareas que vimos en el articulo «Listar elementos en Angular con ngFor«, lo que haremos será tener un botón que permita mostrar o ocultar el listado de tareas.

En este caso al dar click en el botón Mostrar tareas, nos desplegara la lista de tareas y en caso contrario las ocultara, la condición al no ser tan compleja es posible colocarla en el template de html.

tasks.component.html – Directiva ngIf
<button (click)="showTasks = !showTasks">{{showTasks ? 'Ocultar' : 'Mostrar'}} tareas</button>
tasks.component.html
<div class="container">
<div class="title">
Todas mis tareas
<button (click)="showTasks = !showTasks">{{showTasks ? 'Ocultar' : 'Mostrar'}} tareas</button>
</div>
<ng-container *ngIf="showTasks">
<div class="task" *ngFor="let c of tasks; let i = index;trackBy: trackByFn">
<span class="task-id">#{{i}}</span>
<span class="task-description">{{c.description}}</span>
<span class="task-status">{{c.status}}</span>
</div>
</ng-container>
</div>
Ahora veamos el mismo ejemplo pero agregando @else lo que nos permitirá mostrar un valor o un elemento por defecto cuando la primer condición no se cumpla, el cambio que haremos sera que en caso de no haber ninguna tarea mostraremos el texto «Aún no hay tareas en tu lista» y en caso que si haya tareas mostraremos la lista de tareas.
Es importante mencionar que no podemos tener la directiva de ngFor y la directiva ngIf en el mismo div, para ello usaremos un ng-container que nos funcionara como un wrapper y que al renderizar el elemento no nos generara un div adicional. Por otro lado utilizaremos ng-template para resolver el valor por defecto con @else.
En la siguiente imagen no hay ninguna tarea que mostrar, por lo que aunque el primer condicional sea true y se deban mostrar las tareas, el segundo condicional dice que no hay tareas, por lo que debe mostrar «Aún no hay tareas en tu lista».

tasks.component.html – Directiva ngIf con else
// Acción para mostrar u ocultar la lista de elementos
<button (click)="showTasks = !showTasks;">{{showTasks ? 'Ocultar' : 'Mostrar'}} tareas</button>
// Primer condicional que muestra o no la lista de elementos al dar click en el boton
<ng-container *ngIf="showTasks">
...
// Segundo condicional para mostrar un listado de tareas si hay en la lista y si no mostrar el segundo bloque
<ng-container *ngIf="tasks.length > 0; else emptyTasks;">
...
</ng-container>
<ng-template #emptyTasks>
...
</ng-template>
</ng-container>
tasks.component.html – Ejemplo completo
<div class="container">
<div class="title">
Todas mis tareas
<button (click)="showTasks = !showTasks">{{showTasks ? 'Ocultar' : 'Mostrar'}} tareas</button>
</div>
<ng-container *ngIf="showTasks">
<ng-container *ngIf="tasks.length > 0; else emptyTasks;">
<div class="task" *ngFor="let c of tasks; let i = index;trackBy: trackByFn">
<span class="task-id">#{{i}}</span>
<span class="task-description">{{c.description}}</span>
<span class="task-status">{{c.status}}</span>
</div>
</ng-container>
<ng-template #emptyTasks>
<div class="task">
Aún no hay tareas en tu lista
</div>
</ng-template>
</ng-container>
</div>
En el siguiente ejemplo aplicaremos @if, @then y @else, lo que haremos en el ejemplo es que si tenemos muchas tareas de alta prioridad mostraremos el mensaje: «No dejes pasar un día mas, estas por tener tareas difíciles de concluir«, si en su mayoría son tareas de mediana prioridad mostraremos: «Recuerda que tienes tareas importantes por resolver«, si la mayoría son de baja prioridad mostraremos «La mayor cantidad de tus tareas son de baja prioridad«, adicional agregaremos el mensaje en caso que no haya ninguna tarea.

tasks.component.html – ngIf then else
<ng-container *ngIf="tasks.length > 0; then showCorrectMessagesTasks; else emptyTasks;">No se incluye elementos</ng-container>
<ng-template #lowTasks>...</ng-template>
<ng-template #mediumTasks>...</ng-template>
<ng-template #highTasks>...</ng-template>
<ng-template #emptyTasks>...</ng-template>
tasks.component.ts – Ejemplo
@ViewChild('lowTasks', {static: true}) lowTasks: TemplateRef<any>|null = null;
@ViewChild('mediumTasks', {static: true}) mediumTasks: TemplateRef<any>|null = null;
@ViewChild('highTasks', {static: true}) highTasks: TemplateRef<any>|null = null;
tasks.component.html – Ejemplo
<div class="container">
<div class="title">
Todas mis tareas
</div>
<ng-container *ngIf="tasks.length > 0; then showCorrectMessagesTasks; else emptyTasks;">
</ng-container>
<ng-template #lowTasks>
<div class="task task-msg">
La mayor cantidad de tus tareas son de baja prioridad
</div>
</ng-template>
<ng-template #mediumTasks>
<div class="task task-msg">
Recuerda que tienes tareas importantes por resolver
</div>
</ng-template>
<ng-template #highTasks>
<div class="task task-msg">
No dejes pasar un dia mas, estas por tener tareas dificil de concluir.
</div>
</ng-template>
<ng-template #emptyTasks>
<div class="task task-msg">
Aún no hay tareas en tu lista
</div>
</ng-template>
<div class="task" *ngFor="let c of tasks; let i = index;trackBy: trackByFn">
<span class="task-id">#{{i}}</span>
<span class="task-description">{{c.description}}</span>
<span class="task-status">{{c.status}}</span>
</div>
</div>
Ejemplo completo
tasks.component.ts
import {Component, TemplateRef, ViewChild} from '@angular/core';
import {ITask} from "./itask.interface";
import {StatusEnum} from "./status.enum";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'angular-course';
tasks: ITask[] = [
{id: 171, status: StatusEnum.Alta, description: 'Planear actividades', date: '2022-04-01'},
{id: 172, status: StatusEnum.Alta, description: 'Entrenamiento', date: '2022-04-08'},
{id: 173, status: StatusEnum.Media, description: 'Lectura', date: '2022-04-12'},
{id: 174, status: StatusEnum.Alta, description: 'Clases de Frances', date: '2022-05-10'},
{id: 175, status: StatusEnum.Baja, description: 'Natación', date: '2022-05-13'},
{id: 176, status: StatusEnum.Media, description: 'Pagar Facturas', date: '2022-05-17'},
];
@ViewChild('lowTasks', {static: true}) lowTasks: TemplateRef<any>|null = null;
@ViewChild('mediumTasks', {static: true}) mediumTasks: TemplateRef<any>|null = null;
@ViewChild('highTasks', {static: true}) highTasks: TemplateRef<any>|null = null;
/**
* Track By Status task
* @param index
* @param task
*/
trackByFn(index: number, task: ITask) {
return task.status;
}
/**
* Logic to get default message
*/
get showCorrectMessagesTasks() {
if (this.tasks.filter(t => t.status === StatusEnum.Alta).length > 2) {
return this.highTasks
} else if (this.tasks.filter(t => t.status === StatusEnum.Media).length > 2) {
return this.mediumTasks
}
return this.lowTasks;
}
}
tasks.component.html
<div class="container">
<div class="title">
Todas mis tareas
</div>
<ng-container *ngIf="tasks.length > 0; then showCorrectMessagesTasks; else emptyTasks;">
</ng-container>
<ng-template #lowTasks>
<div class="task task-msg">
La mayor cantidad de tus tareas son de baja prioridad
</div>
</ng-template>
<ng-template #mediumTasks>
<div class="task task-msg">
Recuerda que tienes tareas importantes por resolver
</div>
</ng-template>
<ng-template #highTasks>
<div class="task task-msg">
No dejes pasar un dia mas, estas por tener tareas dificil de concluir.
</div>
</ng-template>
<ng-template #emptyTasks>
<div class="task task-msg">
Aún no hay tareas en tu lista
</div>
</ng-template>
<div class="task" *ngFor="let c of tasks; let i = index;trackBy: trackByFn">
<span class="task-id">#{{i}}</span>
<span class="task-description">{{c.description}}</span>
<span class="task-status">{{c.status}}</span>
</div>
</div>
tasks.component.scss
$line: rgb(241, 238, 238);
$primary: #09255e;
$title: #f4f5f6;
$secondary: #fff;
.container {
display: flex;
width: 500px;
flex-direction: column;
align-items: center;
justify-content: center;
margin: 20px;
border-radius: 4px;
border: 1px solid $line;
overflow: hidden;
.title {
background: $title;
width: 100%;
height: 40px;
line-height: 40px;
text-align: center;
font-weight: 500;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 10px;
}
.task {
display: flex;
align-items: center;
width: 100%;
font-size: 12px;
border-bottom: 1px solid $line;
padding: 3px;
height: 30px;
&-msg {
text-align: center;
font-weight: 700;
justify-content: center;
}
&:hover {
background: darken($line, 4);
> .task-description {
text-transform: uppercase;
font-weight: 600;
}
}
&-id {
margin-left: 4px;
font-weight: 600;
}
&-status {
padding: 0 18px;
background: $primary;
border-radius: 20px;
margin: 0 4px;
font-weight: 600;
font-size: 12px;
height: 25px;
line-height: 25px;
color: $secondary;
}
&-description {
width: 100%;
padding: 0 8px;
}
}
}
button {
background: $primary;
color: $secondary;
outline: none;
border: none;
height: 30px;
padding: 0 30px;
border-radius: 30px;
}
status.enum.ts
export enum StatusEnum {
Alta = 'Alta',
Media = 'Media',
Baja = 'Baja'
}
itask.interface.ts
import {StatusEnum} from "./status.enum";
export interface ITask {
id: number;
description: string;
date: string;
status: StatusEnum;
}
Ejemplo complementario – Observables
En este último ejemplo haremos un ejercicio donde emularemos que los datos los recibimos de un servicio web, lo que emularemos será que los datos estan cargando y conforme se agreguen elementos estos aparecerán en el listado de tareas.
tasks.component.html
<ng-container *ngIf="tasksObservable | async as tasks; else emptyTasks">
...
</ng-container>
<ng-template #emptyTasks>
<div class="task task-msg">
...
</div>
</ng-template>
Ejemplo Completo de tareas desde web service
tasks.component.ts
import {Component} from '@angular/core';
import {ITask} from "./itask.interface";
import {StatusEnum} from "./status.enum";
import {Subject} from "rxjs";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'angular-course';
currentTasks: ITask[] = [];
currentTask = 0;
tasks: ITask[] = [
{id: 171, status: StatusEnum.Alta, description: 'Planear actividades', date: '2022-04-01'},
{id: 172, status: StatusEnum.Alta, description: 'Entrenamiento', date: '2022-04-08'},
{id: 173, status: StatusEnum.Media, description: 'Lectura', date: '2022-04-12'},
{id: 174, status: StatusEnum.Alta, description: 'Clases de Frances', date: '2022-05-10'},
{id: 175, status: StatusEnum.Baja, description: 'Natación', date: '2022-05-13'},
{id: 176, status: StatusEnum.Media, description: 'Pagar Facturas', date: '2022-05-17'},
];
tasksObservable = new Subject<ITask[]>();
/**
* Track By Status task
* @param index
* @param task
*/
trackByFn(index: number, task: ITask) {
return task.status;
}
addTask() {
if (this.currentTask <= 5) {
this.currentTasks.push(this.tasks[this.currentTask]);
this.currentTask++;
}
this.tasksObservable.next(this.currentTasks);
}
}
tasks.component.html
<div class="container">
<div class="title">
Todas mis tareas
<button (click)="addTask()">Agregar tarea</button>
</div>
<ng-container *ngIf="tasksObservable | async as tasks; else emptyTasks">
<div class="task" *ngFor="let c of tasks; let i = index;trackBy: trackByFn">
<span class="task-id">#{{i}}</span>
<span class="task-description">{{c.description}}</span>
<span class="task-status">{{c.status}}</span>
</div>
</ng-container>
<ng-template #emptyTasks>
<div class="task task-msg">
Aún no hay tareas en tu lista
</div>
</ng-template>
</div>
Como has podido ver, la directiva ngIf aunque es de las mas importantes y que también es muy sencilla, como has podido leer tiene muchas formas de utilizar, no solo es mostrar u ocultar un elemento, si no que también podemos trabajar con observables, podemos mostrar un elemento u otro en caso de ser necesario, sin necesidad de colocar mas ngIf. Recuerda seguirnos el próximo articulo veremos ngSwitch, aunque es parecido a ngIf nos ayudara a mantener el código más limpio cuando tenemos más de dos posibilidades.