Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Angular Cookbook

You're reading from   Angular Cookbook Over 80 actionable recipes every Angular developer should know

Arrow left icon
Product type Paperback
Published in Dec 2023
Publisher Packt
ISBN-13 9781803233444
Length 536 pages
Edition 2nd Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Muhammad Ahsan Ayaz Muhammad Ahsan Ayaz
Author Profile Icon Muhammad Ahsan Ayaz
Muhammad Ahsan Ayaz
Arrow right icon
View More author details
Toc

Table of Contents (16) Chapters Close

Preface 1. Winning Component Communication 2. Working with Angular Directives and Built-In Control Flow FREE CHAPTER 3. The Magic of Dependency Injection in Angular 4. Understanding Angular Animations 5. Angular and RxJS – Awesomeness Combined 6. Reactive State Management with NgRx 7. Understanding Angular Navigation and Routing 8. Mastering Angular Forms 9. Angular and the Angular CDK 10. Writing Unit Tests in Angular with Jest 11. E2E Tests in Angular with Cypress 12. Performance Optimization in Angular 13. Building PWAs with Angular 14. Other Books You May Enjoy
15. Index

How to apply multiple structural directives to the same element

In certain situations, you might want to use more than one structural directive on the same host or for the same element—for example, a combination of *ngIf and *ngFor together—which is not something Angular supports out of the box. The reason is that it is hard to identify which directive takes precedence over the other, and even if there was a system, I think the apps would become too complex and hard to manage. In this recipe, we will show a message conditionally using *ngIf when we have no items in the bucket. Since we’re supposed to show it conditionally and apply the for loop on the element, this is a perfect example to use for this recipe.

Getting ready

The app that we are going to work with resides in start/apps/chapter02/ng-multi-struc-directives inside the cloned repository:

  1. Open the code repository in your code editor.
  2. Open the terminal, navigate to the code repository directory, and run the following command to serve the project:
    npm run serve ng-multi-struc-directives
    

    This should open the app in a new browser tab, and you should see the following:

    Figure 2.10: ng-multi-struc-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 creating a template for the message to be shown when there are no items in the bucket. We’ll modify the app.component.html file for this as follows:
    <div class="fruits">
        ...
        <ng-template #bucketEmptyMessage>
          <div class="fruits__no-items-msg">
            No items in bucket. Add some fruits!
          </div>
        </ng-template>
    </div>
    
  2. Now we’ll try to apply the *ngIf condition to the element that renders the fruits. Let’s modify the code in the same file, as follows:
    ...
    <div class="fruits">
        <div
          class="fruits__item"
          *ngFor="let item of bucket"
          *ngIf="bucket.length > 0; else bucketEmptyMessage" >...</div>
        <ng-template #bucketEmptyMessage>...</ng-template>
      </div>
    

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

    Figure 2.11: Angular Language Service explaining we can’t use two structural directives on the same element

  1. We can fix this by moving one of the structural directives into a <ng-container> wrapper, which doesn’t create any additional HTML elements in the DOM. Let’s modify the code as follows:
    <div class="fruits">
      <ng-container *ngIf="bucket.length > 0; else
        bucketEmptyMessage">
        <div class="fruits__item" *ngFor="let item of bucket">
          ...
        </div>
      </ng-container>
      <ng-template #bucketEmptyMessage>...</ng-template>
    </div>
    

    With the change above, you should be able to see the message when there are no items in the bucket, as follows:

    Figure 2.12: The final result with *ngIf and *ngFor together

How it works…

Since we can’t use two structural directives on the same element (let’s say a button), we can always use another HTML element as a wrapper (parent) to use one of the structural directive on it, and the other structural directive on the target element (button in our case). However, that adds another element to the DOM and might cause problems for your element hierarchy or other layout behavioral issues, based on your implementation. However, <ng-container> is a magical element from Angular that is not added to the DOM. Instead, it just wraps the logic/condition that you apply to it, which makes it ideal for us to use in cases like these.

See also

You have been reading a chapter from
Angular Cookbook - Second Edition
Published in: Dec 2023
Publisher: Packt
ISBN-13: 9781803233444
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image