Estoy tratando de crear un componente que acepte múltiples plantillas como entradas. Este es el ejemplo que tengo:
@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>; }Como puede ver, es un componente bastante simple que estoy probando. Este componente simplemente acepta los datos de los elementos que se mostrarán, así como la plantilla del elemento. Este componente se puede utilizar así:
<data-list [itemsData]="data"> <ng-template let-item> <h1>{{ item.header }}</h1> <div>{{ item.content }}</div> </ng-template> </data-list> Como se muestra arriba, paso la plantilla usando ng-content que luego lee DataListComponent con @ContentChild(TemplateRef) itemTemplate: TemplateRef<ElementRef>; .
Mi pregunta es si es posible pasar varias plantillas a un componente.
Como ejemplo, se pasaría la plantilla para los artículos, pero se necesita una plantilla diferente en caso de que sea el primer artículo. Esto significaría que la verificación del primer elemento se realizaría en DataListComponent pero luego usaría una plantilla especificada por el componente que la usa.
Ejemplo sencillo:
Puedo hacer algo así para atender esto:
@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> ` }) Sin embargo, así, la "Plantilla siguiente" no está especificada por el componente que usa DataListComponent y, por lo tanto, siempre será la misma plantilla.
Resolví este mismo problema usando el selector de cadenas disponible para el decorador de ContentChild.
Deberá especificar variables de plantilla cuando utilice su componente de lista de datos:
<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>Luego, dentro de su clase de componente de lista de datos, asigne las variables de plantilla a las variables locales en el componente:
@Input() itemsData: any[]; @ContentChild('firstItemTemplate') firstItemTemplate: TemplateRef<ElementRef>; @ContentChild('standardTemplate') standardTemplate: TemplateRef<ElementRef>;Después de esto, podrá representar las plantillas pasadas desde su componente de lista de datos.
@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> ` })Prueba esto en su lugar.
@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>; }