Customized Structural Directives

Intro

A directive class

  • spelled in UpperCamelCase (NgIf).

  • The guide refers to the directive class when talking about its properties and what the directive does.

A directive's attribute name

  • spelled in lowerCamelCase (ngIf).

  • The guide refers to the attribute name when describing how you apply the directive to an element in the HTML template.

Rules

  • The directive attribute name should be spelled in lowerCamelCase and begin with a prefix. Don't use ng. That prefix belongs to Angular.

  • The directive class name ends in Directive per the style guide. Angular's own directives do not.

src/app/unless.directive.ts

import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';

/**
 * Add the template content to the DOM unless the condition is true.
 */
@Directive({ selector: '[appUnless]'})
export class UnlessDirective {
  private hasView = false;

  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainer: ViewContainerRef) { }

  @Input() set appUnless(condition: boolean) {
    if (!condition && !this.hasView) {
      this.viewContainer.createEmbeddedView(this.templateRef);
      this.hasView = true;
    } else if (condition && this.hasView) {
      this.viewContainer.clear();
      this.hasView = false;
    }
  }
}

A simple structural directive like this one creates an embedded view from the Angular-generated<ng-template>and inserts that view in a view container adjacent to the directive's original<p>host element.

You'll acquire the<ng-template>contents with aTemplateRefand access the view container through aViewContainerRef.

You inject both in the directive constructor as private variables of the class.

Angular sets the appUnless property whenever the value of the condition changes. Because the appUnless property does work, it needs a setter.

Last updated

Was this helpful?