问题
I'm trying to create a component that accepts multiple templates as inputs. This is the example I have:
@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>;
}
As you can see it's a fairly simple component that I'm trying out. This component simply accepts the data of the items to be displayed as well as the template of the item. This component can be used like so:
<data-list [itemsData]="data">
<ng-template let-item>
<h1>{{ item.header }}</h1>
<div>{{ item.content }}</div>
</ng-template>
</data-list>
As shown above I'm passing the template using ng-content
which is then read by the DataListComponent
with @ContentChild(TemplateRef) itemTemplate: TemplateRef<ElementRef>;
.
My question is whether it is possible to pass multiple templates to a component.
As an example one would pass the template for the items, but a different template is needed in case it's the first item. This would mean that the check of the first item would be made in the DataListComponent
but then use a template specified by the component using it.
Simple example:
I can do something like so to cater for this:
@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>
`
})
However like so the "Next Template" is not specified by the component using the DataListComponent
and therefore will always be the same template.
回答1:
I solved this same issue by using the string selector available to the ContentChild decorator.
You will need to specify template variables when using your data-list component:
<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>
Then, inside your data-list component class, assign the template variables to local variables on the component:
@Input() itemsData: any[];
@ContentChild('firstItemTemplate') firstItemTemplate: TemplateRef<ElementRef>;
@ContentChild('standardTemplate') standardTemplate: TemplateRef<ElementRef>;
After this, you'll be able to render the passed-in templates from your data-list component.
@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>
`
})
回答2:
Try this instead.
@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>;
}
来源:https://stackoverflow.com/questions/43631813/angular-pass-multiple-templates-to-component