【问题标题】:Angular pass multiple templates to ComponentAngular将多个模板传递给组件
【发布时间】:2017-09-23 17:10:54
【问题描述】:

我正在尝试创建一个接受多个模板作为输入的组件。这是我的例子:

@Component({
    selector: 'data-list',
    styles: [
        require('./data-list.component.scss')
    ],
    template: `
        <ng-template
            *ngFor="let item of itemsData"
            ngFor let-item [ngForOf]="[item]" [ngForTemplate]="itemTemplate"
        ></ng-template>
    `
})

export class DataListComponent {
    @Input() itemsData: any[];
    @ContentChild(TemplateRef) itemTemplate: TemplateRef<ElementRef>;
}

如您所见,这是我正在尝试的一个相当简单的组件。该组件仅接受要显示的项目的数据以及项目的模板。这个组件可以这样使用:

<data-list [itemsData]="data">
    <ng-template let-item>
        <h1>{{ item.header }}</h1>
        <div>{{ item.content }}</div>
    </ng-template>
</data-list>

如上所示,我使用ng-content 传递模板,然后由DataListComponent 和@ContentChild(TemplateRef) itemTemplate: TemplateRef&lt;ElementRef&gt;; 读取。

我的问题是是否可以将多个模板传递给一个组件。

作为示例,我们会传递项目的模板,但如果它是第一个项目,则需要不同的模板。这意味着将在DataListComponent 中对第一项进行检查,然后使用由使用它的组件指定的模板。

简单示例:

我可以这样做来解决这个问题:

@Component({
    selector: 'data-list',
    styles: [
        require('./data-list.component.scss')
    ],
    template: `
        <span *ngFor="let item of itemsData; let i = index" >
            <ng-template *ngIf="i > 0; else nextTmpl"
                ngFor let-item [ngForOf]="[item]" [ngForTemplate]="itemTemplate"
            ></ng-template>
        </span>
        <ng-template #nextTmpl>
            Next
        </ng-template>
    `
})

然而,“下一个模板”不是由使用DataListComponent 的组件指定的,因此将始终是相同的模板。

【问题讨论】:

  • 您的意思是ngIf?
  • 是的,我已经更新了问题,试图更好地解释我的意思。
  • 如果您希望在“外部”上命名您的模板,这是一个更好的方法stackoverflow.com/a/66172026/16940

标签: angular angular-components angular-template


【解决方案1】:

试试这个吧。

@Component({
    selector: 'data-list',
    styles: [
        require('./data-list.component.scss')
    ],
    template: `
        <ng-template ngFor [ngForOf]="itemsData" [ngForTemplate]="itemTemplate"></ng-template>
    `
})

export class DataListComponent {
    @Input() itemsData: any[];
    @ContentChild(TemplateRef) itemTemplate: TemplateRef<ElementRef>;
}

【讨论】:

    【解决方案2】:

    我通过使用 ContentChild 装饰器可用的字符串选择器解决了同样的问题。

    使用数据列表组件时需要指定模板变量:

    <data-list [itemsData]="data">
        <ng-template #firstItemTemplate let-item>
            <h1 style="color:red;">{{ item.header }}</h1>
            <div>{{ item.content }}</div>
        </ng-template>
        <ng-template #standardTemplate let-item>
            <h1>{{ item.header }}</h1>
            <div>{{ item.content }}</div>
        </ng-template>
    </data-list>
    

    然后,在您的数据列表组件类中,将模板变量分配给组件上的局部变量:

    @Input() itemsData: any[];
    @ContentChild('firstItemTemplate') firstItemTemplate: TemplateRef<ElementRef>;
    @ContentChild('standardTemplate') standardTemplate: TemplateRef<ElementRef>;
    

    在此之后,您将能够从数据列表组件呈现传入的模板。

    @Component({
        selector: 'data-list',
        styles: [
            require('./data-list.component.scss')
        ],
        template: `
            <span *ngFor="let item of itemsData; let i = index" >
                <ng-template *ngIf="i == 0; else nextTmpl"
                    ngFor let-item [ngForOf]="[item]" [ngForTemplate]="firstItemTemplate"
                ></ng-template>
                <ng-template #nextTmpl 
                    ngFor let-item [ngForOf]="[item]" [ngForTemplate]="standardTemplate"
                ></ng-template>
            </span>
        `
    })
    

    【讨论】:

    • 这是一种聪明的做法!看起来很整洁 :) 我一定会试一试,然后告诉你进展如何。
    • 这很好,谢谢。我唯一需要添加的是*ngIf="i &gt; 0" #nextTmpl 我知道这有点奇怪,但在下一个模板中我得到了两个模板。
    • 你如何传递索引?
    • @Wei-jye 要传递索引,我建议将data-list 组件模板更改为使用&lt;ng-container *ngTemplateOutlet="standardTemplate; context: { item: item, index: i }"&gt;&lt;/ng-container&gt; 而不是当前的&lt;ng-template ngFor... 方法。可能值得提出一个新问题,具体取决于您要完成的所有工作。
    猜你喜欢
    • 2019-01-02
    • 1970-01-01
    • 2016-11-17
    • 1970-01-01
    • 2019-01-29
    • 2018-08-29
    • 1970-01-01
    • 2017-01-31
    • 2017-10-11
    相关资源
    最近更新 更多