angularangular-componentsangular2-ngcontent

Angular component ng-content passing template with dynamic output placeholders


Is it possible to have a component that can handle dynamic projection like this?

<my-component [date]="2022-03-22">
   <p>This date falls on a <strong #dayName></strong>! It is on week number <span #weekNum></span> of year <span #year></span>.</p>
</my-component>

The HTML code passed into the component has a few ElementRef placeholders for outputting the day name, week number and year based on the date provided in the component @Input.

My roadblock now is my-component fails to detect the ElementRefs when I tried to access them like this:

@Component({
   selector: 'my-component'
})
export class MyComponent implements AfterViewInit {

   @ViewChild('dayName') elemDayName!: ElementRef;
   @ViewChild('weekNum') elemWeekNum!: ElementRef;
   @ViewChild('year') elemYear!: ElementRef;

   ngAfterViewInit() {
      this.elemDayName.nativeElement.innerHTML = 'Tuesday';
      this.elemWeekNum.nativeElement.innerHTML = 12;
      this.elemYear.nativeElement.innerHTML = 2022;
   }
}

Is something like this doable or am I using a wrong method to accomplish this functionality?


Solution

  • For anyone's looking, I managed to solve it this way:

    Parent component

    <my-component [date]="2022-03-22">
       <p>This date falls on a <strong #dayName></strong>! It is on week number <span #weekNum></span> of year <span #year></span>.</p>
    </my-component>
    

    my-component.ts

    @Component({
       selector: 'my-component'
    })
    export class MyComponent implements AfterContentInit {
    
       @Input() date: string;
    
       @ContentChild('dayName') elemDayName!: ElementRef;
       @ContentChild('weekNum') elemWeekNum!: ElementRef;
       @ContentChild('year') elemYear!: ElementRef;
    
       ngAfterContentInit() {
    
          /* do any custom processing as needed and update the template using innerHTML */
    
          this.elemDayName.nativeElement.innerHTML = 'Tuesday';
          this.elemWeekNum.nativeElement.innerHTML = 12;
          this.elemYear.nativeElement.innerHTML = 2022;
       }
    }
    

    my-component.html

    <ng-content></ng-content>