Search code examples
angularangular-content-projectionng-component-outlet

ngComponentOutlet: projected content defined in html


Do you know a way to project content to a component outlet with a content defined in the template it self ?

I've tried following that doesn't work :

@Component({
  template: `<ng-content></ng-content>`,
})
export class MyComp {}

@Component({
  selector: 'my-app',
  standalone: true,
  imports: [CommonModule],
  template: `
    <div *ngComponentOutlet="cmp">
      <div #ref>Ma projection</div>  <!-- I'd like to project this -->
    </div>
  `,
})
export class App {
  cmp = MyComp;
}

I know I can pass content to the *ngComponentOutlet but how could I pass something that is defined in the template, like <div #ref>Ma projection</div> here.

Stackblitz demo


Solution

  • I came up with the following solution :

    @Component({
      selector: 'my-app',
      standalone: true,
      imports: [CommonModule],
      template: `
        <h1>Hello from {{name}}!</h1>
        <ng-template #ref><div>Ma projection</div></ng-template>  <!-- I'd like to project this -->
        <div *ngComponentOutlet="cmp"></div>
      `,
    })
    export class App {
      name = 'Angular';
      cmp = MyComp;
      projectables!: any[][];
      @ViewChild('ref', { static: true }) template!: TemplateRef<any>;
    
      vcr = inject(ViewContainerRef);
    
      ngOnInit() {
        this.projectables = [this.vcr.createEmbeddedView(this.template).rootNodes];
      }
    }
    

    I defined a template that is accessed by a @ViewChild.

    When I have that TemplateRef in ngOnInit, I create a ViewRef that is my projectable content.

    Et voilà.