使用 Angular 2 对话框遇到问题 —— 尝试将它添加到 @NgModule.entryComponents ?

我试图跟随https://material.angular.io/components/component/dialog上的文档,但我不明白为什么它有以下问题?

我在组件上添加了以下内容:

@Component({
selector: 'dialog-result-example-dialog',
templateUrl: './dialog-result-example-dialog.html',
})
export class DialogResultExampleDialog {
constructor(public dialogRef: MdDialogRef) {}
}

在我的模块中我添加了

import { HomeComponent,DialogResultExampleDialog } from './home/home.component';


@NgModule({
declarations: [
AppComponent,
LoginComponent,
DashboardComponent,
HomeComponent,
DialogResultExampleDialog
],


// ...

但是我得到了这个错误....

EXCEPTION: Error in ./HomeComponent class HomeComponent - inline template:53:0 caused by: No component factory found for DialogResultExampleDialog. Did you add it to @NgModule.entryComponents?
ErrorHandler.handleError @ error_handler.js:50
next @ application_ref.js:346
schedulerFn @ async.js:91
SafeSubscriber.__tryOrUnsub @ Subscriber.js:223
SafeSubscriber.next @ Subscriber.js:172
Subscriber._next @ Subscriber.js:125
Subscriber.next @ Subscriber.js:89
Subject.next @ Subject.js:55
EventEmitter.emit @ async.js:77
NgZone.triggerError @ ng_zone.js:329
onHandleError @ ng_zone.js:290
ZoneDelegate.handleError @ zone.js:246
Zone.runTask @ zone.js:154
ZoneTask.invoke @ zone.js:345
error_handler.js:52 ORIGINAL EXCEPTION: No component factory found for DialogResultExampleDialog. Did you add it to @NgModule.entryComponents?
ErrorHandler.handleError @ error_handler.js:52
next @ application_ref.js:346
schedulerFn @ async.js:91
SafeSubscriber.__tryOrUnsub @ Subscriber.js:223
SafeSubscriber.next @ Subscriber.js:172
Subscriber._next @ Subscriber.js:125
Subscriber.next @ Subscriber.js:89
Subject.next @ Subject.js:55
EventEmitter.emit @ async.js:77
NgZone.triggerError @ ng_zone.js:329
onHandleError @ ng_zone.js:290
ZoneDelegate.handleError @ zone.js:246
Zone.runTask @ zone.js:154
ZoneTask.invoke @ zone.js:345
160481 次浏览

Angular 9.0.0 <

从9.0.0版本的Ivy开始,entryComponents属性就不再需要了。看到用法指南

Angular 9.0.0 >

你需要将动态创建的组件添加到你的@NgModule中的entryComponents

@NgModule({
declarations: [
AppComponent,
LoginComponent,
DashboardComponent,
HomeComponent,
DialogResultExampleDialog
],
entryComponents: [DialogResultExampleDialog]

在某些情况下,惰性加载模块下的entryComponents将不起作用,作为一种变通方法,将它们放在你的app.module(根目录)中

你需要在@NgModule下使用entryComponents

这适用于使用ViewContainerRef.createComponent()添加的动态添加的组件。将它们添加到entryComponents告诉脱机模板编译器编译它们并为它们创建工厂。

在路由配置中注册的组件也会自动添加到entryComponents中,因为router-outlet也使用ViewContainerRef.createComponent()将路由组件添加到DOM中。

所以你的代码就像

@NgModule({
declarations: [
AppComponent,
LoginComponent,
DashboardComponent,
HomeComponent,
DialogResultExampleDialog
],
entryComponents: [DialogResultExampleDialog]

发生这种情况是因为这是一个动态的组件,而你没有将它添加到@NgModule下的entryComponents中。

简单地添加到这里:

@NgModule({
/* ----------------- */
entryComponents: [ DialogResultExampleDialog ] // <---- Add it here

看看角的团队是如何谈论entryComponents的:

entryComponents?: Array<Type<any>|any[]>

指定 定义此模块时应编译的组件。为 对于这里列出的每个组件,Angular都会创建一个ComponentFactory和 将它存储在ComponentFactoryResolver中

另外,这是@NgModule上的方法列表,包括entryComponents

正如你所看到的,它们都是可选的(看看问号),包括entryComponents,它接受一个组件数组:

@NgModule({
providers?: Provider[]
declarations?: Array<Type<any>|any[]>
imports?: Array<Type<any>|ModuleWithProviders|any[]>
exports?: Array<Type<any>|any[]>
entryComponents?: Array<Type<any>|any[]>
bootstrap?: Array<Type<any>|any[]>
schemas?: Array<SchemaMetadata|any[]>
id?: string
})

虽然集成材质对话框是可能的,但我发现这样一个微不足道的功能的复杂性是相当高的。如果您试图实现非平凡的特性,那么代码将变得更加复杂。

出于这个原因,我最终使用了PrimeNG对话框,我发现它使用起来非常简单:

m-dialog.component.html:

<p-dialog header="Title">
Content
</p-dialog>

m-dialog.component.ts:

@Component({
selector: 'm-dialog',
templateUrl: 'm-dialog.component.html',
styleUrls: ['./m-dialog.component.css']
})
export class MDialogComponent {
// dialog logic here
}

m-dialog.module.ts:

import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import { DialogModule } from "primeng/primeng";
import { FormsModule } from "@angular/forms";


@NgModule({
imports: [
CommonModule,
FormsModule,
DialogModule
],
exports: [
MDialogComponent,
],
declarations: [
MDialogComponent
]
})
export class MDialogModule {}

简单地将对话框添加到组件的html中:

<m-dialog [isVisible]="true"> </m-dialog>

PrimeNG PrimeFaces文档很容易理解并且非常精确。

如果你和我一样,盯着这个线程想“但是我不是在尝试添加一个组件,我是在尝试添加一个守卫/服务/管道等”,那么问题很可能是你在路由路径中添加了错误的类型。我就是这么做的。我不小心在路径的组件:部分中添加了一个保护,而不是canActivate:部分。我喜欢IDE自动完成,但你必须放慢一点,并注意。如果你真的找不到它,就对它抱怨的名字进行全局搜索,并查看每一个用法,以确保你没有弄错名字。

在我的例子中,我将我的组件添加到declarations和entryComponents中,得到了相同的错误。我还需要将MatDialogModule添加到导入。

如果你试图在服务中使用MatDialog -让我们称其为'PopupService',该服务在一个模块中定义:

@Injectable({ providedIn: 'root' })

那么它可能不会起作用。我正在使用惰性加载,但不确定这是否相关。

你必须:

  • 将你的PopupService直接提供给打开对话框的组件——使用[ provide: PopupService ]。这允许它(通过DI)使用组件中的MatDialog实例。我认为在这个实例中调用open的组件需要与dialog组件在同一个模块中。
  • 将对话框组件移到app.module中(就像其他答案所说的那样)
  • 调用服务时传递matDialog的引用。

请原谅我混乱的回答,重点是它是providedIn: 'root'打破东西,因为MatDialog需要从一个组件。

在惰性加载的情况下,你只需要在惰性加载模块中导入MatDialogModule。然后这个模块将能够用它自己导入的MatDialogModule呈现入口组件:

@NgModule({
imports:[
MatDialogModule
],
declarations: [
AppComponent,
LoginComponent,
DashboardComponent,
HomeComponent,
DialogResultExampleDialog
],
entryComponents: [DialogResultExampleDialog]

你必须把它添加到entryComponents中,就像在文档. c中指定的那样。

@NgModule({
imports: [
// ...
],
entryComponents: [
DialogInvokingComponent,
DialogResultExampleDialog
],
declarations: [
DialogInvokingComponent,
DialogResultExampleDialog
],
// ...
})

下面是一个应用程序模块文件的完整的例子,其中的对话框定义为entryComponents

如果有人需要从服务中调用对话,这里是如何解决问题的。 我同意上面的一些回答,我的答案是,如果有人在服务上遇到问题,可以调用对话

创建一个服务,例如DialogService,然后将你的dialog函数移动到服务内部,并在你调用的组件中添加你的DialogService,如下所示:

 @Component({
selector: "app-newsfeed",
templateUrl: "./abc.component.html",
styleUrls: ["./abc.component.css",],
providers:[DialogService]
})

否则就会出错

我有同样的问题,我在EntryComponents中有dialogComponent,它仍然不工作。这就是我解决问题的方法。这里是以前回答过的帖子的链接:

https://stackoverflow.com/a/64224799/14385758 < a href = " https://stackoverflow.com/a/64224799/14385758 " > < / >