Skip to content

Instantly share code, notes, and snippets.

@WodenWang820118
Last active January 28, 2023 08:31
Show Gist options
  • Save WodenWang820118/57b5b5a8cfd494167b705d2c78c0b11f to your computer and use it in GitHub Desktop.
Save WodenWang820118/57b5b5a8cfd494167b705d2c78c0b11f to your computer and use it in GitHub Desktop.
// 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment