Angular ContentChildren获取指令Inputs和TemplateRef

时间:2018-01-10 18:41:24

标签: angular angular2-template

我正在为TemplateRefng-template参数获取input app.component.html:

<my-parent>
    <ng-template my-directive title="Title1" let-dataItem="dataItem">
        <div>{{dataItem|json}}</div>
    </ng-template>
</my-parent>

问题是我只能获得TemplateRef(标题未定义):
我的-parent.html:

<div *ngFor="let detail of details" [title]="detail.title"> //!!! detail.title is undefined
  <ng-container *ngTemplateOutlet="detail;context:{dataItem: dataItem}"></ng-container>
</div>

MY-parent.ts

@ContentChildren(MyDirective, { read: TemplateRef }) details: QueryList<MyDirective>;

或者我可以获得输入参数:
我的-parent.ts

@ContentChildren(MyDirective) details: QueryList<MyDirective>;   

//in html detail.title is defined, but detail is not template and I get exception in line 
<ng-container *ngTemplateOutlet="detail;context:{dataItem: dataItem}"></ng-container>

例外:

TypeError: templateRef.createEmbeddedView is not a function

我想我需要这个版本的ContentChildren:

@ContentChildren(MyDirective, { read: TemplateRef }) details: QueryList<MyDirective>;

但是如何在这种情况下获得MyDirective输入参数(title)?

我知道我可以同时使用两者:

@ContentChildren(MyDirective, { read: TemplateRef }) detailsRefs: QueryList<MyDirective>;
@ContentChildren(MyDirective) detailsInputs: QueryList<MyDirective>;

然后将其合并到新数组中:

public ngAfterViewInit(): void
{
  const refs = this.detailsRefs.toArray();
  const inputs = this.detailsInputs.toArray();
  for (let i = 0; i < inputs.length; i++)
    this.details.push({templateRef: refs[i], inputs: inputs[i]});
}

但确定有更好的方法。

2 个答案:

答案 0 :(得分:3)

可以使用DI来完成:

@Directive({
  selector: '[my-directive]'
})
export class MyDirective  {
  @Input() title: string;

  constructor(public templateRef: TemplateRef<any>) {}
}

现在应该很容易理解我们可以利用前面的指令,如:

<强> parent.component.ts

@ContentChildren(MyDirective) details: QueryList<MyDirective>;

<强> parent.component.html

<ng-container *ngTemplateOutlet="detail.templateRef
                                       ^^^^^^^^^^^^^

<强> Stackblitz Example

答案 1 :(得分:1)

您可以使用title中的输入阅读my-directive,然后从那里阅读,因为您需要删除{read: TemplateRef}

@ContentChildren(MyDirective) details: QueryList<MyDirective>;
...
detail.title

据我记得结构指令,输入需要以选择器为前缀。

@Directive({ selector: 'myDirective', ...})
class MyDirective {
  @Input() myDirectiveTitle:string;
}

并像

一样使用它
 <ng-template myDirective title="Title1" let-dataItem="dataItem">

并使用

阅读标题
detail.myDirectiveTitle

另见https://angular.io/guide/structural-directives

此代码

@ContentChildren(MyDirective, { read: TemplateRef }) details: QueryList<MyDirective>;

会导致错误,因为当您阅读TemplateRef时,detail应为QueryList<TemplateRef>类型。

相关问题