Since we know how to dynamically render Events from an array, let's give some shape to our app.

1. Style Event component

  1. Update the event.component.html template with the following code
  2. <div class="media">
              <h3 class="h3-responsive font-weight-bold mr-3">{{ value.time }}</h3>
              <div class="media-body mb-3">
                <mdb-badge danger="true" class="text-center float-right">-</mdb-badge>
                <h6 class="mt-0 font-weight-bold">{{ value.subject }}</h6>
                <hr class="hr-bold mb-0 my-2" />
                <p class="mb-0">
                  <mdb-icon fas icon="location-arrow"></mdb-icon>
                  {{ value.location }}
                </p>
              </div>
            </div>
            <p class="p-3 blue-grey lighten-5 blue-grey lighten-5">
              {{ value.description }}
            </p>
  3. Save and run project
  4. Preview

    Our project starts looking good. However, we have some empty parts. Some of our events don't have decsription or/nor location. This is a perfect use case to use conditional rendering.

2. ngIf

One of the reasons why Angular has grown so fast recently is the fact that it comes with a variety of predefined directives like ngFor which you already know. In this lesson, we will learn how to use ngIf.

Let's have a look at our description paragraph:

<p class="p-3 blue-grey lighten-5 blue-grey lighten-5" >
          {{ value.description }}
        </p>

We can easily define whether we want to render entire paragraph using simple if condition:

<p *ngIf="true"> I am rendered! </p>
        <p *ngIf="false"> I am not :( </p>

Of course we don't want to set it globally, instead we want to display paragraph depending on whether description exists. In order to do that we can simply provide it as an argument to the ngIf directive:

<p class="p-3 blue-grey lighten-5 blue-grey lighten-5" *ngIf="value.description">
          {{ value.description }}
        </p>

The empty description paragraph is gone now

Now let's do the same with paragraph including location

<div class="media">
          <h3 class="h3-responsive font-weight-bold mr-3">{{ value.time }}</h3>
          <div class="media-body mb-3 ">
            <mdb-badge danger="true" class="text-center float-right">-</mdb-badge>
            <h6 class="mt-0 font-weight-bold">{{ value.subject }}</h6>
            <hr class="hr-bold mb-0 my-2" />
            <p class="mb-0" *ngIf="value.location">
              <mdb-icon fas icon="location-arrow"></mdb-icon>
              {{ value.location }}
            </p>
          </div>
        </div>
        <p class="p-3 blue-grey lighten-5 blue-grey lighten-5" *ngIf="value.description">
          {{ value.description }}
        </p>

Which solves our original issue:

Preview

3. If-else

3.1 Angular templates (<ng-template>)

In a previous lesson we have mentioned about templates within Angular. In order to understand how the else condtition works we have to start with understanding what templates are.

Like the name indicates, the <ng-template> directive represents an Angular template: this means that the content of this tag will contain part of a template, that can be composed together with other templates in order to form the final component template.

<ng-template> is a template element that Angular uses with structural directives (*ngIf, *ngFor, [ngSwitch] and custom directives).

Let's get started learning <ng-template> with an example

<div *ngIf="isLogged; else loggedOut">
            Welcome back, friend.
          </div>
        
          <ng-template #loggedOut>
            Please friend, login.
          </ng-template>
        <p class="p-3 blue-grey lighten-5 blue-grey lighten-5" *ngIf="value.description">
          {{ value.description }}
        </p>

The main two things worth noticing here are the template reference variable (the #loggedOut - which you can call whatever you like) and also the <ng-template>. We use the <ng-template> because much like it’s HTML5 counterpart <template>, it’s also considered “virtual”.

Being “virtual” means the contents won’t actually exist in the compiled DOM, until it’s needed. When it’s needed (for example the “else” expression kicks into play), Angular will grab the contents of the tag, and replace the *ngIf contents with it.

That’s it. It’s just a virtual container that won’t render any contents until it’s ready.

So, before we continue, where does this * asterisk come from?

It’s all about sugar syntax. When we do this:

<div *ngIf="isLoggedIn">
          Welcome back, friend.
        </div>

With our new found knowledge, we can now understand that it’s equivalent to this:

<ng-template [ngIf]="isLoggedIn">
          <div>
            Welcome back, friend.
          </div>
        </ng-template>

Angular will convert our *ngIf syntax across to the above, which I’m sure you’ll agree isn’t quite as fast to work with. It does however tell us more about what’s happening with [ngIf], which is the directive being bound with a property binding syntax. Yes, this does mean, we can supply ngIf, ngIfElse (and ngIfThen) the same way.

3.2 If-else

Let's get back to our use case

<div *ngIf="isLogged; else loggedOut">
            Welcome back, friend.
          </div>
        
          <ng-template #loggedOut>
            Please friend, login.
          </ng-template>
        <p class="p-3 blue-grey lighten-5 blue-grey lighten-5" *ngIf="value.description">
          {{ value.description }}
        </p>

As you can expect, if isLogged variable will evaluate to true, Angular will render
Welcome back, friend.
message. However, in case of isLogged beeing false (or not existing at all), it will print
Please friend, login.

You could optionally adopt this approach to create a more descriptive if/then/else block. Again, use cases and preferences.

<ng-container
          *ngIf="isLoggedIn; then loggedIn; else loggedOut">
        </ng-container>
        
        <ng-template #loggedIn>
          <div>
            Welcome back, friend.
          </div>
        </ng-template>
        <ng-template #loggedOut>
          <div>
            Please friend, login.
          </div>
        </ng-template>

Warning:
It is important to remember that it is impossible to use two structural directive (i.e. ngFor and ngIf) within a single tag at the same time!