在Angular2中使用ngFor进行多次包含 [英] Multiple transclusion using ngFor in Angular2

查看:174
本文介绍了在Angular2中使用ngFor进行多次包含的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在angular2上还很陌生,我正在尝试制作一个名为" grid "的小角度组件,该组件只是使用包含来重新排列其内容.

I'm pretty new in angular2 and I'm trying to make a small angular component called "grid" that simply rearranges its content using transclusion.

其模板

<div class="grid">
  <div class="row">
    <div class="col-xs-4">
      <ng-content select="[grid-item-index=0]"></ng-content>
    </div>
    <div class="col-xs-4">
      <ng-content select="[grid-item-index=1]"></ng-content>
    </div>
    <div class="col-xs-4">
      <ng-content select="[grid-item-index=2]"></ng-content>
    </div>
  </div>
  <div class="row">
    <div class="col-xs-4">
      <ng-content select="[grid-item-index=3]"></ng-content>
    </div>
    <div class="col-xs-4">
      <ng-content select="[grid-item-index=4]"></ng-content>
    </div>
    <div class="col-xs-4">
      <ng-content select="[grid-item-index=5]"></ng-content>
    </div>
  </div>
</div>

这是使用它的父组件的一部分.

And this is part of the parent component that uses it.

<grid>
  <div *ngFor="let item of items; index as i" [attr.grid-item-index]="i">
    <span>{{item}}</span>
  </div>
</grid>

这是一个柱塞.

但是结果不显示任何内容.但是使用...

But the result displays no content. But using...

<grid>
  <div grid-item-index="0">item 0</div>
  <div grid-item-index="1">item 1</div>
  <div grid-item-index="2">item 2</div>
  <div grid-item-index="3">item 3</div>
  <div grid-item-index="4">item 4</div>
  <div grid-item-index="5">item 5</div>
</grid>

它工作正常,结果与我预期的一样.

it works fine and the result was as I expected.

最后一个工作案例的柱塞.

A Plunker of this last working case.

可以使用ngfor或类似工具实现此结果.

Can achieve this result using a ngfor or similar.

我尝试使用nth-child css伪类来避免使用索引,但是它也不起作用.

I've tried using nth-child css pseudo class to avoid using the index but it doesn't work too.

基于@yurzui(谢谢!)的回答,我已经取得了一些进展.它允许将具有 grid-item-index 值的内容映射到具有相同 grid-item-index 值的视图容器.

I've made some progress based on @yurzui (Thanks!!) answer. It allows to map content with an grid-item-index value to the view container with the same grid-item-index value.

<grid>
    <ng-template *ngFor="let item of items; let i=index" 
    [grid-item-index]="(items.length-1)-i">
        <span >{{item}}</span>
    </ng-template> 
</grid>

grid-item-index指令

@Directive({
  selector: '[grid-item-index]'
})
export class GridItemIndexDirective {
  @Input('grid-item-index') index: any;

  constructor(public vcRef: ViewContainerRef, public tRef: TemplateRef) {}
}

grid.component.ts

@ContentChildren(GridItemIndexDirective) sources: QueryList<GridItemIndexDirective>;
  @ViewChildren(GridItemIndexDirective) containers: QueryList<GridItemIndexDirective>;

  constructor(
    private cdRef:ChangeDetectorRef
  ) {}

  ngAfterViewInit() {
    const len = this.sources.length;
    for (var i = 0; i < len; i++) {
      const destinationContainer = this.containers.find(x => x.index == i);
      const source = this.sources.find(x => x.index == i);
      if (destinationContainer) {
        destinationContainer.vcRef.createEmbeddedView(source.tRef);
        this.cdRef.detectChanges(); // this solves ExpressionChangedAfterItHasBeenCheckedError
      }
    }
  }

选中此柱塞

推荐答案

您可以使用 ngTemplateOutlet 来实现这一点,但是还有另一种使用低级API的方法:

You can use ngTemplateOutlet to achieve this but there is another approach that uses low-level API:

parent.component.html

<grid>
  <div *ngFor="let item of items">
    <span>{{item}}</span>
  </div>
</grid>

其他指令,它将帮助我们识别目标索引.

Additional directive that will help us to recognize destination index.

@Directive({
  selector: '[grid-item-index]'
})
export class GridItemIndexDirective {
  @Input('grid-item-index') index: any;

  constructor(public vcRef: ViewContainerRef) {}
}

grid.component.html

<div class="grid">
  <div class="row">
    <div class="col-xs-4">
      <ng-template grid-item-index="1"></ng-template>
    </div>
    <div class="col-xs-4">
      <ng-template grid-item-index="2"></ng-template>
    </div>
    <div class="col-xs-4">
      <ng-template grid-item-index="3"></ng-template>
    </div>
  </div>
  <div class="row">
    <div class="col-xs-4">
      <ng-template grid-item-index="4"></ng-template>
    </div>
    <div class="col-xs-4">
      <ng-template grid-item-index="5"></ng-template>
    </div>
    <div class="col-xs-4">
      <ng-template grid-item-index="6"></ng-template>
    </div>
  </div>
</div>

grid.component.ts

@ContentChild(TemplateRef, { read: ViewContainerRef }) vcRef: ViewContainerRef;
@ViewChildren(GridItemIndexDirective) containers: QueryList<GridItemIndexDirective>;

ngAfterViewInit() {
  const len = this.vcRef.length;
  for( var i = 1; i <= len; i++) {
    const destinationContainer = this.containers.find(x => x.index == i);
    if(destinationContainer) {
      const view = this.vcRef.detach(0);
      destinationContainer.vcRef.insert(view);
    }
  }
}

柱塞示例

Plunker Example

这篇关于在Angular2中使用ngFor进行多次包含的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆