ngComponentOutlet: проецируемый контент, определенный в html.

Знаете ли вы, как проецировать контент на выход компонента с контентом, определенным в самом шаблоне?

Я пробовал следующее, но это не работает:

      @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;
}

Я знаю, что могу пройтиcontentк*ngComponentOutletно как я могу передать что-то, что определено в шаблоне, например<div #ref>Ma projection</div>здесь.

Демо-версия Stackblitz

2 ответа

Я придумал следующее решение:

      @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];
  }
}

Я определил шаблон, к которому обращается@ViewChild.

Когда у меня это будетTemplateRefвngOnInit, я создаюViewRefэто мой проецируемый контент.

И вуаля.

Вы можете использовать ViewChild для ссылки на содержимое шаблона, а затем передать его в выход компонента с помощью createEmbeddedView и прикрепить.

      import { Component, ViewChild, AfterViewInit, ViewContainerRef, ComponentFactoryResolver } from '@angular/core';
import { CommonModule } from '@angular/common';

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

@Component({
  selector: 'my-app',
  standalone: true,
  imports: [CommonModule],
  template: `
    <div #container></div>
  `,
})
export class App implements AfterViewInit {
  @ViewChild('container', { read: ViewContainerRef, static: true }) container: ViewContainerRef;

  constructor(private cfr: ComponentFactoryResolver) {}

  ngAfterViewInit() {
    const factory = this.cfr.resolveComponentFactory(MyComp);
    const componentRef = this.container.createComponent(factory);
    const templateRef = this.container.createEmbeddedView(this.ref.nativeElement);
    componentRef.instance.viewRef = templateRef;
    componentRef.changeDetectorRef.detectChanges();
    this.container.detach();
  }
}

ViewChild , чтобы получить ссылку на ViewContainerRef элемента div с переменной шаблона #container. Затем в хуке жизненного цикла ngAfterViewInit мы создаем фабрику компонентов для MyComp и используем ее для создания нового экземпляра компонента. Мы также создаем встроенное представление содержимого, определенное переменной шаблона #ref, с помощью createEmbeddedView, и прикрепляем его к экземпляру компонента с помощью instance.viewRef .

надеюсь, это поможет ..!

Другие вопросы по тегам