Как я могу реализовать директиву, которая оборачивает содержимое своего HostElement в div? - PullRequest
0 голосов
/ 07 марта 2020

Мне нужно реализовать директиву, которая добавляет элементы HTML внутри его элемента хоста, а также помещает все содержимое элемента в определенную c часть HTML, по сути, оборачивая содержимое, подобно тому, как Angular Материал оборачивает содержимое <button mat-button> <span class="mat-button-wrapper">.

Например, компонент будет помещен в шаблон, подобный следующему:

<div my-directive>
    my text
</div>

И это должно быть rendered:

<div my-directive>
    <div class="my-class">
        my text
    </div>
</div>

Я пытался использовать WrapperComponent и добавить его в ViewContainerRef директивы, как показано ниже.

import { Directive, TemplateRef, ViewContainerRef, Component, Renderer2, ElementRef, ComponentFactoryResolver, ViewChild, ComponentRef } from '@angular/core';

@Component({
    selector: 'my-wrapper',
    template: `
        <div class="my-wrapper">
            <ng-content></ng-content>
        </div>
    `
})
export class WrapperComponent {
}

@Directive({
    selector: '[wrapContent]'
})
export class WrapContentDirective{

    wrapperRef: ComponentRef<WrapperComponent>;

    constructor(
        private renderer: Renderer2,
        private templateRef: TemplateRef<any>,
        private vcr: ViewContainerRef,
        private cfr: ComponentFactoryResolver,
        hostElement: ElementRef
    ) {
        const wrapperFactory = this.cfr.resolveComponentFactory(WrapperComponent);
        this.wrapperRef = this.vcr.createComponent(wrapperFactory);
    }
}

Но оболочка отображается рядом с элементом, и не внутри И мне все еще нужно выяснить, как проецировать содержимое ng-контента в WrapperComponent.

Как я могу это реализовать?

1 Ответ

0 голосов
/ 07 марта 2020

Создайте компонент с нужным вам шаблоном, я называю его DynoComponent. Этот компонент будет создан динамически, и для него будет установлен шаблон для использования с [ngTemplateOutlet].

Создайте директиву, которая будет захватывать TemplateRef и ViewContainerRef хоста, и создайте DynoComponent динамически и установите для него свойство шаблона.

DynoComponent html

<div class="my-class">
  <ng-template [ngTemplateOutlet]='template'></ng-template>
</div>

DynoComponent ts

@Component({
  selector: 'app-dyno',
  templateUrl: './dyno.component.html',
  styleUrls: ['./dyno.component.css']
})
export class DynoComponent implements OnInit {

  template: TemplateRef<any>;

  constructor() { }

  ngOnInit(): void {
  }

}

Моя директива

@Directive({
  selector: '[appMyDirective]'
})
export class MyDirectiveDirective implements OnInit {
  compRef: ComponentRef<DynoComponent>;
  constructor(private vcRef: ViewContainerRef,
              private templateRef: TemplateRef<any>,
              private compFact: ComponentFactoryResolver) { }

  ngOnInit() {
    const myComp = this.compFact.resolveComponentFactory(DynoComponent);
    this.compRef = this.vcRef.createComponent(myComp);
    this.compRef.instance.template = this.templateRef;
  }

}

Как использовать в других шаблонах

<div class="outer" *appMyDirective>
  <p>inside content</p>
</div>

Вывод

<div _ngcontent-acn-c18="" class="my-class">
    <div _ngcontent-acn-c20="" class="outer">
        <p _ngcontent-acn-c20="">inside content</p>
    </div>
    <!--bindings={
      "ng-reflect-ng-template-outlet": "[object Object]"
    }-->
</div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...