使用 NgComponentOutlet 进行动态内容投影的 Angular 渲染组件

问题描述 投票:0回答:1
    <mat-button-toggle-group appearance="legacy"    [(ngModel)]="selectedClockType">
        <mat-button-toggle *ngFor="let item of items" [value]="item" color="primary">
           {{ item.label }}
        </mat-button-toggle>  
    </mat-button-toggle-group>
       
     @for (item of items; track:item.id) {   
          <ng-container *ngComponentOutlet="item .component"></ng-container> 
        }

     <ng-template #actionItesm let-data="data">{{data}} </ng-template>

组件-a.html

    <ng-content></ng-content>

组件-b.html

<ng-content></ng-content>

我正在尝试使用下面的代码来传递 ngTemplate

 <ng-container *ngComponentOutlet="item .component;content: actionItesm ></ng-container> 

并在Items

中使用的所有组件中使用
javascript angular angular17
1个回答
0
投票

您需要使用

createEmbeddedView
ViewContainerRef
,其中我们输入模板作为第一个参数,然后是包含模板上下文的第二个参数。我创建了一个新属性
templateRef
,其中包含创建的模板引用结构。最后我们将该输入传递给
content
 的属性 
*ngComponentOutlet

NgComponentOutlet中提到的示例是理解步骤和过程的一个很好的例子。

完整代码:

家长TS:

import { CommonModule } from '@angular/common';
import {
  Component,
  ViewChild,
  ViewContainerRef,
  TemplateRef,
  Injector,
} from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { AComponent } from 'src/app/a/a.component';
import { BComponent } from 'src/app/b/b.component';

/**
 * @title Basic button-toggles
 */
@Component({
  selector: 'button-toggle-overview-example',
  templateUrl: 'button-toggle-overview-example.html',
  standalone: true,
  imports: [
    MatButtonToggleModule,
    CommonModule,
    AComponent,
    BComponent,
    FormsModule,
  ],
})
export class ButtonToggleOverviewExample {
  @ViewChild('actionItesm', { static: true }) actionItesm!: TemplateRef<any>;
  selectedClockType: any;
  items: Array<any> = [
    { id: 1, label: 'a', component: AComponent },
    { id: 2, label: 'b', component: BComponent },
  ];
  myContent?: any[][];
  myInjector: Injector;

  constructor(injector: Injector, private vcr: ViewContainerRef) {
    this.myInjector = injector;
  }

  ngOnInit() {
    // Create the projectable content from the templates
    if (this.items?.length) {
      this.items.forEach((item: any) => {
        item.templateRef = [
          this.vcr.createEmbeddedView(this.actionItesm, { item: item })
            .rootNodes,
        ];
      });
    }
  }
}

父级 HTML:

<mat-button-toggle-group appearance="legacy" [(ngModel)]="selectedClockType">
  <mat-button-toggle *ngFor="let item of items" [value]="item" color="primary">
    {{ item.label }}
  </mat-button-toggle>
</mat-button-toggle-group>
<br />
<br />
<br />
@for (item of items; track item.id;) { {{item.label}}
<ng-container
  *ngComponentOutlet="item.component;
  content: item.templateRef;"
></ng-container>
}
<ng-template #actionItesm let-item="item">{{item.label}} asdf</ng-template>

儿童TS:

import { Component } from '@angular/core';

@Component({
  selector: 'app-b',
  standalone: true,
  imports: [],
  templateUrl: './b.component.html',
  styleUrl: './b.component.scss'
})
export class BComponent {

}

子 HTML:

<br />
<hr />
B COMPONENT
<ng-content></ng-content>
<hr />
<br />

Stackblitz 演示

© www.soinside.com 2019 - 2024. All rights reserved.