Angular 如何实现封装其HostElement';div中的内容是什么?

Angular 如何实现封装其HostElement';div中的内容是什么?,angular,Angular,我需要实现一个指令,将HTML元素添加到其宿主元素中,同时将元素的所有内容放在HTML的特定部分,本质上是包装内容,就像Angle Material如何用包装的内容一样 例如,组件将放在如下模板中: <div my-directive> my text </div> 我的文字 这应该是: <div my-directive> <div class="my-class"> my text </div

我需要实现一个指令,将HTML元素添加到其宿主元素中,同时将元素的所有内容放在HTML的特定部分,本质上是包装内容,就像Angle Material如何用
包装
的内容一样

例如,组件将放在如下模板中:

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

我的文字
这应该是:

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

我的文字
我尝试使用包装器组件并将其添加到指令的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);
    }
}
import{指令,TemplateRef,ViewContainerRef,组件,RenderR2,ElementRef,ComponentFactoryResolver,ViewChild,ComponentRef}从'@angular/core'导入;
@组成部分({
选择器:“我的包装器”,
模板:`
`
})
导出类包装器组件{
}
@指示({
选择器:“[wrapContent]”
})
导出类WrapContentDirective{
wrapperRef:ComponentRef;
建造师(
私有渲染器:渲染器2,
私有templateRef:templateRef,
私人录像机:ViewContainerRef,
专用cfr:ComponentFactoryResolver,
招待员:ElementRef
) {
const wrapperFactory=此.cfr.resolveComponentFactory(WrapperComponent);
this.wrapperRef=this.vcr.createComponent(wrapperFactory);
}
}
但是包装器呈现在元素旁边,而不是元素内部。我仍然需要弄清楚如何将ng内容的内容投影到WrapperComponent中


如何实现这一点?

使用所需的模板创建一个组件,我称之为DynoComponent。此组件将动态创建,并将模板设置为与
[ngTemplateOutlet]
一起使用

创建一个指令,该指令将捕获主机的
TemplateRef
ViewContainerRef
,并动态创建
DynoComponent
,并在其上设置模板属性

动态组件html

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

动态组件ts

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

  template: TemplateRef<any>;

  constructor() { }

  ngOnInit(): void {
  }

}
<div class="outer" *appMyDirective>
  <p>inside content</p>
</div>
@组件({
选择器:“应用程序动态”,
templateUrl:“./dyno.component.html”,
样式URL:['./dyno.component.css']
})
导出类DynoComponent实现OnInit{
模板:TemplateRef;
构造函数(){}
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;
  }

}
@指令({
选择器:“[appMyDirective]”
})
导出类MyDirectiveDirective实现OnInit{
ComponentRef:ComponentRef;
构造函数(专用vcRef:ViewContainerRef,
私有templateRef:templateRef,
私有compFact:ComponentFactoryResolver){}
恩戈尼尼特(){
const mycop=this.compFact.resolveComponentFactory(DynoComponent);
this.compRef=this.vcreef.createComponent(myComp);
this.compRef.instance.template=this.templateRef;
}
}
如何在其他模板中使用

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

  template: TemplateRef<any>;

  constructor() { }

  ngOnInit(): void {
  }

}
<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>

内部内容


感谢您的回复。我考虑过使用结构化指令,但我试图避免使用*指令。不过,我想这是正确的方法。我想知道棱角材料是怎么做的。无论如何谢谢你!您可以添加与TemplateRef类型的指令同名的setter输入,并在宿主元素上使用它,如[appMyDirective]=“TemplateRef”,其中TemplateRef可以是ng模板的本地引用。基本上,这样你就不必使用*。我只是测试了一下。它可以工作,但我的目标是只包装元素的内容。解决方案包装了所有内容,包括最初附加到指令的元素。