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

Posted

技术标签:

【中文标题】在 angular2 中构建一个包装器指令(包装一些内容/组件)【英文标题】:Building a wrapper directive (wrap some content / component) in angular2 【发布时间】:2017-05-01 03:09:53 【问题描述】:

我是 Angular2 的全新构建指令。我想要的是创建一个弹出指令,它将用一些 css 类包装内容。

内容

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

<div class="data">
    <h2>Header</h2>
    Content to be placed here.
</div>

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

<div class="data" popup>
    <h2>Header</h2>
    Content to be placed here.
</div>

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

<div class="some class">
    <div class="some other class">
        <div class="data">
            <h2>Header</h2>
            Content to be placed here.
        </div>
    </div>
</div>

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

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

@Directive(
  selector: `[popup]`
)

export class PopupDirective 



【问题讨论】:

【参考方案1】:

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

如需更详细的信息,请参阅:How to conditionally wrap a div around ng-content - 我的解决方案适用于 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>;

我的指令是这样的:

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;
  

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

@NgModule(
  imports: [CommonModule],
  declarations: [WrapperContainerComponent, WrapperDirective],
  exports: [WrapperContainerComponent, WrapperDirective],
  entryComponents: [WrapperContainerComponent]
)
export class MyModule

所以最后的html是:

<some_tag *myWrapperDirective />

呈现为:

<my-wrapper-container>
  <div class="whatever">
    <some_tag />
  </div>
</my-wrapper-container>

【讨论】:

@Input set 方法中的控制来自哪里?另外,SubmissionGroup 是从哪里来的?我找不到任何文档。 哇。这是由于我为之执行此操作的实际项目中粘贴了一些错误的复制粘贴。当我有一些时,我会清理它...... 这是相关答案,看不懂其他的+7... 越来越近...当您使用 ` *myWrapperDirective` 而不是 *myWraperDirective 时会有所帮助 :) 很惊讶它没有给出无法识别该名称的错误。 看起来当您以这种方式包装输入时,# 元素引用无法正常工作。例如,这总是为错误显示 null:&lt;input type="text" name="age" #ageRef="ngModel" [(ngModel)]="age" required *myWrapperDirective /&gt; &lt;pre&gt;ageRef?.errors | json&lt;/pre&gt; 如果您将 &lt;input&gt; 和使用元素 ref 的代码都包装在同一个 &lt;div *myWrapperDirective&gt; 中,它会起作用...但如果您需要,这不起作用整个父组件的元素引用。知道如何“导出”元素 ref 以在指令之外使用吗?【参考方案2】:

您可以使用组件属性选择器和 Angular 2 内容投影&lt;ng-content&gt; 来实现这一点

@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 


【讨论】:

这显然只适用于接受内容的元素。就此而言,它在用于输入元素时不起作用。 这实际上似乎并没有达到@Mikkel 的要求。这将包裹 [myWrapper] 所在元素的内部,而不是将该模板包裹在它所在的信息周围。 这很好用。将此与 Angular 7 一起使用。但还有一件事,而不是指令,将其用作组件,因为 Angular 样式指南不推荐 [compname]。 这不是我们所要求的——它用指令包装了元素的内容,而不是用指令包装了实际组件。在您的示例中,&lt;div class="data" myWrapper&gt; 应该被包装。

以上是关于在 angular2 中构建一个包装器指令(包装一些内容/组件)的主要内容,如果未能解决你的问题,请参考以下文章

Angular2:渲染一个没有包装标签的组件

Angular 2:从属性指令获取对组件属性的引用

OpenCL:如何使用 C++ 包装器检查构建错误

设计模式之“Decorator”注疏#02

使用 java-ffmpeg 包装器,还是简单地使用 java 运行时来执行 ffmpeg?

我是不是需要(或应该)将我所有的 Vue 组件包装在一个包装器组件中?