Book Image

Angular Cookbook

By : Muhammad Ahsan Ayaz
Book Image

Angular Cookbook

By: Muhammad Ahsan Ayaz

Overview of this book

The Angular framework, powered by Google, is the framework of choice for many web development projects built across varying scales. It’s known to provide much-needed stability and a rich tooling ecosystem for building production-ready web and mobile apps. This recipe-based guide enables you to learn Angular concepts in depth using a step-by-step approach. You’ll explore a wide range of recipes across key tasks in web development that will help you build high-performance apps. The book starts by taking you through core Angular concepts such as Angular components, directives, and services to get you ready for building frontend web apps. You’ll develop web components with Angular and go on to cover advanced concepts such as dynamic components loading and state management with NgRx for achieving real-time performance. Later chapters will focus on recipes for effectively testing your Angular apps to make them fail-safe, before progressing to techniques for optimizing your app’s performance. Finally, you’ll create Progressive Web Apps (PWA) with Angular to provide an intuitive experience for users. By the end of this Angular book, you’ll be able to create full-fledged, professional-looking Angular apps and have the skills you need for frontend development, which are crucial for an enterprise Angular developer.
Table of Contents (15 chapters)

How to use *ngIf and *ngSwitch together

In certain situations, you might want to use more than one structural directive on the same host—for example, a combination of *ngIf and *ngFor together. In this recipe, you'll learn how to do exactly that.

Getting ready

The project we are going to work with resides in chapter02/start_here/multi-structural-directives, inside the cloned repository:

  1. Open the project in VS Code.
  2. Open the terminal, and run npm install to install the dependencies of the project.
  3. Once done, run ng serve -o.

    This should open the app in a new browser tab, and you should see something like this:

Figure 2.6 – multi-structural-directives app running on http://localhost:4200

Figure 2.6 – multi-structural-directives app running on http://localhost:4200

Now that we have the app running, let's see the steps for this recipe in the next section.

How to do it…

  1. We'll start by moving the element with the No items in bucket. Add some fruits! text into its own <ng-template> element, and we'll give it a template variable called #bucketEmptyMessage. The code should look like this in the app.component.html file:
    …
    <div class="content" role="main">
     ...
      <div class="page-section">
        <h2>Bucket <i class="material-icons">shopping_cart     </i></h2>
        <div class="fruits">
          <div class="fruits__item" *ngFor="let item of       bucket;">
            <div class="fruits__item__title">{{item.name}}        </div>
            <div class="fruits__item__delete-icon"         (click)="deleteFromBucket(item)">
              <div class="material-icons">delete</div>
            </div>
          </div>
        </div>
      </div>
      <ng-template #bucketEmptyMessage>
        <div class="fruits__no-items-msg">
          No items in bucket. Add some fruits!
        </div>
      </ng-template>
    </div>
  2. Notice that we moved the entire div out of the .page-section div. Now, we'll use the ngIf-Else syntax to either show a bucket list or an empty bucket message based on the bucket's length. Let's modify the code, as follows:
    ...
    <div class="content" role="main">
      ...
      <div class="page-section">
        <h2>Bucket <i class="material-icons">shopping_cart     </i></h2>
        <div class="fruits">
          <div *ngIf="bucket.length > 0; else       bucketEmptyMessage" class="fruits__item"       *ngFor="let item of bucket;">
            <div class="fruits__item__title">{{item.name}}        </div>
            <div class="fruits__item__delete-icon"         (click)="deleteFromBucket(item)">
              <div class="material-icons">delete</div>
            </div>
          </div>
        </div>
      </div>
    ...
    </div>

    As soon as you save the preceding code, you'll see the application breaks, mentioning we can't use multiple template bindings on one element. This means we can't use multiple structural directives on one element:

    Figure 2.7 – Error on console, showing we can't use multiple directives on one element

    Figure 2.7 – Error on console, showing we can't use multiple directives on one element

  3. Now, as a final step, let's fix the issue by wrapping the div with *ngFor="let item of bucket;" inside an <ng-container> element and using the *ngIf directive on the <ng-container> element, as follows:
    ...
    <div class="content" role="main">
      ...
      <div class="page-section">
        <h2>Bucket <i class="material-icons">shopping_cart     </i></h2>
        <div class="fruits">
          <ng-container *ngIf="bucket.length > 0; else       bucketEmptyMessage">
            <div class="fruits__item" *ngFor="let item         of bucket;">
              <div class="fruits__item__title">{{item.          name}}</div>
              <div class="fruits__item__delete-icon"           (click)="deleteFromBucket(item)">
                <div class="material-icons">delete</div>
              </div>
            </div>
          </ng-container>
        </div>
      </div>
    </div>

How it works…

Since we can't use two structural directives on a single element, we can always use another HTML element as a parent to use the other structural directive. However, that adds another element to the DOM and might cause problems for your element hierarchy, based on your implementation. <ng-container>, however, is a magical element from Angular's core that is not added to the DOM. Instead, it just wraps the logic/condition that you apply to it, which makes it really easy for us to just add a *ngIf or *ngSwitchCase directive on top of your existing elements.

See also