在angular2中构建一个包装器指令(包装一些内容/组件)

Mik*_*kel 13 html angular-template angular2-directives angular

我是Angular2的新建筑指令.我想要的是创建一个弹出指令,将一些css类包装内容.

内容

内容可以是纯文本和标题,如:

<div class="data">
    <h2>Header</h2>
    Content to be placed here.
</div>
Run Code Online (Sandbox Code Playgroud)

然后我想给它一个指令属性,如:popup

<div class="data" popup>
    <h2>Header</h2>
    Content to be placed here.
</div>
Run Code Online (Sandbox Code Playgroud)

该指令应该做的是将div包装在里面,让我们说:

<div class="some class">
    <div class="some other class">
        <div class="data">
            <h2>Header</h2>
            Content to be placed here.
        </div>
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)

我到目前为止描述的情况,这是一个属性或结构指令.

import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({
  selector: `[popup]`
})

export class PopupDirective {


}
Run Code Online (Sandbox Code Playgroud)

Dan*_*eld 12

另一个答案是相关但不同的.

对于更接近的事情,请参阅:如何有条件地围绕ng-content包装div - 我的解决方案适用于Angular 4,但链接的问题有一些关于Angular 2如何可行的提示.

我用组件和指令组合解决了这个问题.我的组件看起来像这样:

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

@Component({
  selector: 'my-wrapper-container',
  template: `
<div class="whatever">
  <ng-container *ngTemplateOutlet="template"></ng-container>
</div>
`
})
export class WrapperContainerComponent {
  @Input() template: TemplateRef<any>;
}
Run Code Online (Sandbox Code Playgroud)

我的指令是这样的:

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

@Directive({
  selector: '[myWrapperDirective]'
})
export class WrapperDirective implements OnInit {

  private wrapperContainer: ComponentRef<WrapperContainerComponent>;

  constructor(
    private templateRef: TemplateRef<any>,
    private viewContainerRef: ViewContainerRef,
    private componentFactoryResolver: ComponentFactoryResolver
  ) { }

  ngOnInit() {
    const containerFactory = this.componentFactoryResolver.resolveComponentFactory(WrapperContainerComponent);
    this.wrapperContainer = this.viewContainerRef.createComponent(containerFactory);
    this.wrapperContainer.instance.template = this.templateRef;
  }
}
Run Code Online (Sandbox Code Playgroud)

为了能够动态加载组件,您需要将组件列为entryComponent模块内部:

@NgModule({
  imports: [CommonModule],
  declarations: [WrapperContainerComponent, WrapperDirective],
  exports: [WrapperContainerComponent, WrapperDirective],
  entryComponents: [WrapperContainerComponent]
})
export class MyModule{}
Run Code Online (Sandbox Code Playgroud)

所以HTML到底是:

<some_tag *myWrapperDirective />
Run Code Online (Sandbox Code Playgroud)

其呈现为:

<my-wrapper-container>
  <div class="whatever">
    <some_tag />
  </div>
</my-wrapper-container>
Run Code Online (Sandbox Code Playgroud)


Kld*_*Kld 8

您可以使用组件属性选择器和Angular 2内容投影来实现此目的 <ng-content>

@Component({
  selector: 'my-app',
  template: `
    <div class="app"> 
        <div class="data" myWrapper>
            <h2>Header</h2>
            Content to be placed here.
        </div> 
    </div>
  `
})
export class AppComponent {}


@Component({
  selector: '[myWrapper]',
  template: `
    <div class="my-class">
      <div class="my-sub-class">
          <ng-content></ng-content>
      </div>
    </div>
  `
})
export class MyComponent {

}
Run Code Online (Sandbox Code Playgroud)

  • 这实际上似乎并没有像@Mikkel那样做.这将包裹放置[myWrapper]的elemnt的内部,而不是将该模板包裹在它所放置的信息周围. (6认同)
  • 这应该标记为正确的答案. (3认同)
  • 显然,这仅适用于接受内容的元素。因此,在输入元素上使用时,它将无法正常工作。 (2认同)