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)

Writing your first custom structural directive

In this recipe, you'll write your first custom structural directive named *appIfNot that will do the opposite of what *ngIf does—that is, you'll provide a Boolean value to the directive, and it will show the content attached to the directive when the value is false, as opposed to how the *ngIf directive shows the content when the value provided is true.

Getting ready

The project for this recipe resides in chapter02/start_here/ng-if-not-directive:

  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.4 – ng-if-not-directive app running on http://localhost:4200

Figure 2.4 – ng-if-not-directive app running on http://localhost:4200

How to do it…

  1. First of all, we'll create a directive using the following command in the project root:
    ng g directive directives/if-not
  2. Now, instead of the *ngIf directive in the app.component.html file, we can use our *appIfNot directive. We'll also reverse the condition from visibility === VISIBILITY.Off to visibility === VISIBILITY.On, as follows:
    ...
    <div class="content" role="main">
      ...
      <div class="page-section" id="resources"   *appIfNot="visibility === VISIBILITY.On">
        <!-- Resources -->
        <h2>Content to show when visibility is off</h2>
      </div>
    </div>
  3. Now that we have set the condition, we need to create an @Input inside the *appIfNot directive that accepts a Boolean value. We'll use a setter to intercept the value changes and will log the value on the console for now:
    import { Directive, Input } from '@angular/core';
    @Directive({
      selector: '[appIfNot]'
    })
    export class IfNotDirective {
      constructor() { }
      @Input() set appIfNot(value: boolean) {
        console.log(`appIfNot value is ${value}`);
      }
    }
  4. If you tap on the Visibility On and Visibility Off buttons now, you should see the values being changed and reflected on the console, as follows:
    Figure 2.5 – Console logs displaying changes for the appIfNot directive values

    Figure 2.5 – Console logs displaying changes for the appIfNot directive values

  5. Now, we're moving toward the actual implementation of showing and hiding the content based on the value being false and true respectively, and for that, we first need the TemplateRef service and the ViewContainerRef service injected into the constructor of if-not.directive.ts. Let's add these, as follows:
    import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
    @Directive({
      selector: '[appIfNot]'
    })
    export class IfNotDirective {
      constructor(private templateRef: TemplateRef<any>,   private viewContainerRef: ViewContainerRef) { }
      @Input() set appIfNot(value: boolean) {
        console.log(`appIfNot value is ${value}`);
      }
    }
  6. Finally, we can add the logic to add/remove the content from the DOM based on the appIfNot input's value, as follows:
    ...
    export class IfNotDirective {
      constructor(private templateRef: TemplateRef<any>,   private viewContainerRef: ViewContainerRef) { }
      @Input() set appIfNot(value: boolean) {
        if (value === false) {
          this.viewContainerRef.      createEmbeddedView(this.templateRef);
        } else {
          this.viewContainerRef.clear()
        }
      }
    }

How it works…

Structural directives in Angular are special for multiple reasons. First, they allow you to manipulate DOM elements—that is, adding/removing/manipulating based on your needs. Moreover, they have this * prefix that binds to all the magic Angular does behind the scenes. As an example, *ngIf and *ngFor are both structural directives that behind the scenes work with the <ng-template> directive containing the content you bind the directive to and create the required variables/properties for you in the scope of ng-template. In the recipe, we do the same. We use the TemplateRef service to access the <ng-template> directive that Angular creates for us behind the scenes, containing the host element on which our appIfNot directive is applied. Then, based on the value provided to the directive as input, we decide whether to add the magical ng-template to the view or clear the ViewContainerRef service to remove anything inside it.

See also