You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular:如何通过Injector在ngComponentOutlet中传值及解决组件创建报错

问题:Angular动态创建组件时提示"No component factory found for [object Object]"

我尝试在Angular中动态创建并展示组件,需要向其传递数据来展示内容,但遇到了报错。以下是我的代码:

HTML代码

<div class="basicContainer">
 <div class="projectsTreeContainer">
 <input type="text" id="searchWord" placeholder="Search through projects"/>
 <button (click)="loadAddProject()">Add new Project</button>
 <app-projects-tree (onLoadProjectDetails)="loadProjectDetails($event)" (onLoadWpDetails)="loadWpDetails($event)" (onSelectAndLoadJobDetails)="loadJobDetails($event)"></app-projects-tree>
 </div>
 <div class="infoContainer">
 <ng-container *ngComponentOutlet="details"></ng-container>
 </div>
</div>

父组件代码

export class ProjectsComponent implements OnInit {
 details: Component;
 private showWp: boolean;
 constructor() { }
 loadProjectDetails(project: BasicProject): void {
 this.details = new ProjectComponent(project);
 }
}

目标动态组件代码

export class ProjectComponent implements OnInit {
 project: Project;
 constructor(basicProject: BasicProject) {
 this.project = new Project();
 this.project.name = basicProject.name ;
 }
}

NgModule配置

@NgModule({
 declarations: [
 AppComponent,
 NavbarComponent,
 LoginComponent,
 ProjectsComponent,
 ProjectComponent,
 ProjectsTreeComponent,
 TreeProjectComponent,
 TreeWpComponent,
 WpComponent,
 JobComponent,
 AddProjectComponent
 ],
 imports: [
 BrowserModule,
 FormsModule,
 RouterModule.forRoot(
 AppRoutes.appRoutes,
 // {enableTracing: true} // <-- debugging purposes only
 ),
 HttpClientModule,
 HttpModule
 ],
 providers: [
 AuthenticationService,
 ProjectsService,
 CanActivateAuthGuard,
 { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }],
 bootstrap: [AppComponent],
 entryComponents: [ProjectComponent, WpComponent, JobComponent, AddProjectComponent]
})

报错信息

ProjectsComponent.html:15 ERROR Error: No component factory found for [object Object].

请问该如何解决这个问题,完成动态创建组件并传递数据的需求?


解决方案

你遇到的核心问题是直接实例化组件类(new ProjectComponent(...))不符合Angular的组件创建机制,Angular需要通过组件工厂来创建组件实例,而且*ngComponentOutlet接受的是组件类型(比如ProjectComponent),而不是已经实例化的对象。下面是具体的修复步骤:

1. 修正父组件中组件类型的定义与创建逻辑

首先,details应该存储组件的类型,而不是实例。同时注入ComponentFactoryResolver来处理组件创建:

import { Component, OnInit, ComponentFactoryResolver, Injector } from '@angular/core';
import { ProjectComponent } from './project.component';
import { BasicProject } from './models/basic-project.model';

export class ProjectsComponent implements OnInit {
  // 存储要展示的组件类型
  detailsComponentType: any;
  // 存储当前要传递的项目数据
  currentProject: BasicProject;

  constructor(
    private componentFactoryResolver: ComponentFactoryResolver,
    private injector: Injector
  ) { }

  loadProjectDetails(project: BasicProject): void {
    this.currentProject = project;
    // 赋值组件类型,而非实例
    this.detailsComponentType = ProjectComponent;
  }

  // 创建自定义注入器,用于传递数据
  createProjectInjector(): Injector {
    return Injector.create({
      parent: this.injector,
      providers: [{ provide: BasicProject, useValue: this.currentProject }]
    });
  }
}

2. 修改HTML模板,通过*ngComponentOutlet传递数据

*ngComponentOutlet支持通过自定义注入器传递依赖,调整模板如下:

<div class="infoContainer">
  <ng-container *ngComponentOutlet="detailsComponentType; injector: createProjectInjector()"></ng-container>
</div>

3. 调整目标组件的构造函数,通过依赖注入获取数据

目标组件不能直接在构造函数中接收普通参数,需要通过Angular的依赖注入机制获取数据:

import { Component, OnInit, Inject } from '@angular/core';
import { BasicProject } from './models/basic-project.model';
import { Project } from './models/project.model';

export class ProjectComponent implements OnInit {
  project: Project;

  constructor(@Inject(BasicProject) private basicProject: BasicProject) {
    this.project = new Project();
    this.project.name = basicProject.name;
  }

  ngOnInit(): void {
    // 可在此添加更多初始化逻辑
  }
}

4. 确认entryComponents配置(Angular 9+可省略)

你的NgModule中已经将ProjectComponent加入entryComponents,这在Angular 9之前是动态组件必须的配置(用于提前编译)。Angular 9及以后启用Ivy编译器后,该配置可省略,但保留也不会有问题。

备选方案:手动创建组件实例(更精细控制)

如果需要对组件实例做更多自定义操作,也可以手动通过ComponentFactoryResolver创建组件:

首先在父组件模板中添加容器引用:

<div class="infoContainer">
  <div #dynamicComponentContainer></div>
</div>

然后修改父组件代码:

import { Component, OnInit, ComponentFactoryResolver, ViewChild, ViewContainerRef } from '@angular/core';

export class ProjectsComponent implements OnInit {
  @ViewChild('dynamicComponentContainer', { read: ViewContainerRef }) container: ViewContainerRef;

  constructor(private componentFactoryResolver: ComponentFactoryResolver) { }

  loadProjectDetails(project: BasicProject): void {
    // 清空容器内已有组件
    this.container.clear();
    // 获取组件工厂
    const factory = this.componentFactoryResolver.resolveComponentFactory(ProjectComponent);
    // 创建组件实例
    const componentRef = this.container.createComponent(factory);
    // 直接给组件实例赋值数据(无需依赖注入)
    componentRef.instance.project = new Project({ name: project.name });
  }
}

这样修改后,就能正确实现动态创建组件并传递数据的需求了。核心是要遵循Angular的组件生命周期和依赖注入机制,不要直接实例化组件类。

内容的提问来源于stack exchange,提问作者Unknwn Artist

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:52:42