[Angular] Step-By-Step Implementation of a Structural Directive

For example we have two buttons:

When we click nether one of those tow button, the modal should show up:

We will use structure directive to do that.

So create a new directive 'auModalOpenOnClick':

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

@Directive({
  selector: '[auModalOpenOnClick]'
})
export class AuModalOpenOnClickDirective { 

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

A stucture need to use 'TemplateRef' and 'ViewContainerRef'. You can simply think that templateRef refer to the html you are going to show/hide. ViewContainerRef refers to the container that wrap the template/compoent, normally it should be <ng-template>.

HTML:

  <ng-template [auModalOpenOnClick]="[loginButton, signUpButton]">
    <au-modal class="auth-modal">
       <!-- modal content goes here-->
    </au-modal>
  </ng-template>

  <div class="modal-buttons">

    <button #loginButton>Login</button>

    <button #signUpButton>Sign Up</button>

  </div>    

So the way we use the directive is that it takes a input which can be array of template ref or just a single templateRef.

We are going to check in the directive, if the passed in templateRef(s) are clicked or not, if it is click, we are going to create a embbed view based on the template (au-modal) we got.

directive:

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

@Directive({
  selector: '[auModalOpenOnClick]'
})
export class AuModalOpenOnClickDirective {

  @Input()
  set auModalOpenOnClick (els) {

    let elements: HTMLBaseElement[];

    if(Array.isArray(els)) {
      elements = els;
    } else {
      elements = [els];
    }

    elements.forEach(el => {
      el.addEventListener('click', () => {
        this.viewContainer.clear();
        this.viewContainer.createEmbeddedView(this.template);
      });
    });
  }

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

}

And also worth to mention that:

  <ng-template [auModalOpenOnClick]="[loginButton, signUpButton]">
    <au-modal class="auth-modal">
       <!-- modal body-->
    </au-modal>
  </ng-template>

the same as:

    <au-modal class="auth-modal"*auModalOpenOnClick="[loginButton, signUpButton]">
     <!-- modal body-->
    </au-modal>    
原文地址:https://www.cnblogs.com/Answer1215/p/7097028.html