Angular2 ngFor父元素

3

我正在尝试对我的Bootstrap col-xs-4进行条件包裹,每行三个。我的col-xs-4正常渲染,但我无法弄清楚如何在条件下将它们包裹在一行中。以下是我的当前NgFor:

 <div class="col-xs-4" *ngFor='let linkGroup of linkGroups | siteMapText: siteMapTextFilter; let i=index'>
        <ul class="list-unstyled">
            <li class="heading">
                <div class="clearfix">
                    <span [className]="linkGroup.ContainerCssClass">
                        <span [className]="linkGroup.CssClass"></span>
                    </span>
                    <a href="#">
                        <strong class="heading-text">{{linkGroup.Title}}</strong>
                    </a>
                </div>
            </li>
            <li *ngFor='let link of linkGroup.Links'>
                <a href="#" class="link">
                    <span [className]="link.CssClass"></span>
                    <span class="item">{{link.Title}}</span>
                </a>
            </li>
        </ul>
    </div>

我想做的是像这样的事情,但我知道这是错误的,那么正确的方法是什么?
 <div *ngIf='i % 3== 0' class="row">
        <div class="col-xs-4" *ngFor='let linkGroup of linkGroups | siteMapText: siteMapTextFilter; let i=index'>
            <ul class="list-unstyled">
                <li class="heading">
                    <div class="clearfix">
                        <span [className]="linkGroup.ContainerCssClass">
                            <span [className]="linkGroup.CssClass"></span>
                        </span>
                        <a href="#">
                            <strong class="heading-text">{{linkGroup.Title}}</strong>
                        </a>
                    </div>
                </li>
                <li *ngFor='let link of linkGroup.Links'>
                    <a href="#" class="link">
                        <span [className]="link.CssClass"></span>
                        <span class="item">{{link.Title}}</span>
                    </a>
                </li>
            </ul>
        </div>
    </div>

编辑

正如Gunter所建议的那样,答案是重新组织数据以分组为行。然后我可以将模板组织成这样:

<div class="row" *ngFor='let linkRow of linkRows| siteMapRowText: siteMapTextFilter'>
    <div class="col-xs-4" *ngFor='let rowCol of linkRow.RowGroups'>
        <ul class="list-unstyled">
            <li class="heading">
                <div class="clearfix">
                    <span [className]="rowCol.ContainerCssClass">
                        <span [className]="rowCol.CssClass"></span>
                    </span>
                    <a href="#">
                        <strong class="heading-text">{{rowCol.Title}}</strong>
                    </a>
                </div>
            </li>
            <li *ngFor='let link of rowCol.Links'>
                <a href="#" class="link">
                    <span [className]="link.CssClass"></span>
                    <span class="item">{{link.Title}}</span>
                </a>
            </li>
        </ul>
    </div>
</div>

不确定我的答案是否符合您的实际需求。也许您想要将<div class="row">包装4个linkGroup,而不仅仅是每组4个中的第一个。这需要对我的代码进行重新组织。 - Günter Zöchbauer
ngif 标签是关于 .Net 而不是 Angular 的。您可以使用 angular-ng-if - 030
1个回答

4

更新

您可以使用一个管道来创建一个新数组,将4个项目分组成一个数组,这样您就可以得到一个数组的数组,然后使用嵌套的ngFor。

@Pipe({ name: 'cols' })
export class ColsPipe implements PipeTransform {
    transform(value: any[], cols: number) {
        var result: any[] = [];
        while(value.length) {
            result.push(value.splice(0, cols));
        }
        return result;
    }
};

参见如何使用JavaScript将长数组拆分成小数组,然后像这样使用它:
@NgModule({
  declarations: [ColsPipe],
  exports: [ColsPipe]
})
class MySharedModule()

@NgModule({
  imports: [MySharedModule],
  ...
})
class ModuleWhereColsPipeIsUsed {}

@Component({
  selector: '...',
  template: `
  <div class="row" *ngFor='let linkGroupRow of linkGroups | siteMapText: siteMapTextFilter | cols:4; let i=index'>
    <div class="col-xs-4" *ngFor='let linkGroup of linkGroupRow'>...</div>
  </div>
  `
})    

翻译

可以使用ngTemplateOutlet来实现这一点。

首先,我们创建一个可重复使用的组件:

<template #linkGroupTemplate>
    <div class="col-xs-4">
        <ul class="list-unstyled" let-linkGroup="linkGroup"
                >
            <li class="heading">
                <div class="clearfix">
                    <span [className]="linkGroup.ContainerCssClass">
                        <span [className]="linkGroup.CssClass"></span>
                    </span>
                    <a href="#">
                        <strong class="heading-text">{{linkGroup.Title}}</strong>
                    </a>
                </div>
            </li>
            <li *ngFor='let link of linkGroup.Links'>
                <a href="#" class="link">
                    <span [className]="link.CssClass"></span>
                    <span class="item">{{link.Title}}</span>
                </a>
            </li>
        </ul>
    </div>
</template>

“let-linkGroup="linkGroup"” 声明了一个上下文变量“linkGroup”,它引用传递上下文的 "linGroup" 属性。
然后我们在 ngFor 内部使用该模板,并将其用
包装在每个第4项上,否则不包装。
<template ngFor let-linkGroup [ngForOf]="linkGroups |siteMapText:siteMapTextFilter" let-i="index">
  <template [ngIf]="i % 3 === 0">
    <div class="row">
     <template [ngTemplateOutlet]="linkGroupTemplate" [ngOutletContext]="{'linkGroup': linkGroup}">
    </div>
  <template>

  <template [ngIf]="i % 3 !== 0">
     <template [ngTemplateOutlet]="linkGroupTemplate" [ngOutletContext]="{'linkGroup': linkGroup}">
  </template>
</template>

<ng-container *ngFor="let linkGroup of linkGroups |siteMapText:siteMapTextFilter" let-i="index">
  <ng-container *ngIf="i % 3 === 0">
    <div class="row">
     <template [ngTemplateOutlet]="linkGroupTemplate" [ngOutletContext]="{'linkGroup': linkGroup}"></template>
    </div>
  <ng-container>

  <ng-container *ngIf="i % 3 !== 0">
     <template [ngTemplateOutlet]="linkGroupTemplate" [ngOutletContext]="{'linkGroup': linkGroup}"></template>
  </ng-container>
</ng-container>

使用 [ngOutletContext]="{'linkGroup': linkGroup}",我们将实际的 linkGroup 值包装在另一个对象中,以便我们可以像模板中一样访问它。否则,我们需要为每个要使用的属性声明一个变量。
let-CssContainerCssClass="ContainerCssClass" let-CssClass="CssClass" let-Title="Title" let-Links="Links" 

将所有绑定中的 linkGroup. 删除。
另请参见 如何在不使用 ngFor 和另一个 @Component 的情况下多次重复 HTML 片段,其中包含使用 ngTemplateOutletngOutletContext 的示例(带有 Plunker)。

这真的很接近,谢谢你指向了routerOutlet。但它正在将第一列包装成自己的行,然后在行元素之外渲染出下面两列。我想要的是在一行的div里面有三列。 - cobolstinks
我明白了。我已经有这个怀疑了。这就是为什么我在你的问题下面发表评论的原因。您可以使用一个管道来创建一个新数组,将4个项目分组成一个数组,这样您就可以得到一个数组的数组,然后使用嵌套的 ngFor - Günter Zöchbauer
我更新了我的答案,展示了管道示例的样子。 - Günter Zöchbauer
这对我很有效。我的 Angular 版本不允许使用 "pipes: [ColsPipe]",我必须将 ColPipes 放入我的应用程序模块的声明中,然后该管道就可以在我的模板中访问了。 - David Lee
谢谢你的提示。@Component() 中的 pipes 早就被移除了。我已经更新了我的答案。 - Günter Zöchbauer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接