Reputation: 1169
I'm attempting to create a generic slideshow component which will take multiple components, and then it will loop through based on certain user actions.
It's very similar to the Angular Material's stepper component.
So far, I've figured out that you can use @ContentChildren
to get references to multiple (passed in) components/content, but I'm not sure how to actually render the components.
Here's an example I created: https://stackblitz.com/edit/angular-yjfbwb
The app.component.html file contains a <tours></tours>
tag which you can pass in anything you want as long as you tag it with #tour
. And inside the tours.component.ts, you'll see that I'm just looping through the passed in components.
But how do I actually render them?
I've googled around, and it seems like it's not possible the way I'm doing it? But perhaps I'm not searching properly. Ideally, I would like to make this tours component as simple to use as possible (basically how it is in the example above) for my team.
Any help would be greatly appreciated!
Upvotes: 3
Views: 3401
Reputation: 2823
There are a lot of ways to achive this.
Here is a simple solution. Just to get the idea. You may want to do it differently according to your exact problem.
For every element you like to project in your tours component you have to create a Template. You can do this via a StructuralDirective
.
import {Directive, TemplateRef, Input} from '@angular/core';
@Directive({
selector: '[appTour]'
})
export class TourDirective {
@Input('appTour') id: number;
constructor(public template: TemplateRef<any>) {
}
}
Mark the elements inside your ToursComponent
with the directive (Don't forget the asterisk):
<tours>
<p *appTour="123">hello</p>
<p *appTour="1234">world</p>
</tours>
To identify the directives you can pass for example the id
of the tour to your template.
Now inside your ToursComponent
inject the TourDirective
via @ContentChildren
and pass the template you like to render inside a ViewContainerRef | <ng-container>
import { Component, ContentChildren, QueryList } from '@angular/core';
import { TourDirective } from './tour.directive';
@Component({
selector: 'tours',
template: `
<ng-container *ngFor="let tour of tours.toArray()">
<ng-container *ngIf="tour.id === tourToDisplay">
<ng-container [ngTemplateOutlet]="tour.template"></ng-container>
</ng-container>
</ng-container>`,
})
export class ToursComponent {
public tourToDisplay = 123;
@ContentChildren(TourDirective) tours: QueryList<TourDirective>;
}
Upvotes: 7