// supposed in the standalone courseCardComponent
// extract template and class Input() property only
template: `
<ng-container *ngIf="course">
<div class="course-card" [ngClass]="cardClasses()">
<div class="course-title">
{{ cardIndex + " " + course.description }}
</div>
<!-- can apply select attribute to only project certain tags, or classes -->
<ng-content
select="course-image"
*ngIf="course.iconUrl; else noImage"
></ng-content>
<!-- instantiate ng-template using *ngTemplateOutlet directive -->
<ng-template #noImage>
<ng-container
*ngTemplateOutlet="
noImageTpl;
context: { description: course.description }
"
></ng-container>
</ng-template>
</div>
</ng-container>
// class
export class CourseCardComponent {
@Input() noImageTpl: TemplateRef<any>;
}
// parent component: app.component.html
<div class="courses">
// define the template to be input in the course card component
// could be separated as component also, but using ng-template reduces nubmer of files
// and could be performant
<ng-template #blankImage let-courseName="description">
<p class="warn">{{ courseName }} has no image yet.</p>
<img src="/assets/empty-image.png" />
</ng-template>
// input the blankImage ng-template
// instantiate it in the course card component
<course-card
*ngFor="let course of courses; index as i"
(courseSelected)="onCourseSelected($event)"
[course]="course"
[cardIndex]="i + 1"
[noImageTpl]="blankImage"
>
<!-- the nested content will be projected with ng-content in the course-card component -->
<!-- it is used when building the generic components, and fill in the content accordingly -->
<!-- can project component inside another component -->
<course-image [src]="course.iconUrl"></course-image>
</course-card>
</div>