【问题标题】:Angular2 material dialog has issues - Did you add it to @NgModule.entryComponents?Angular2 材质对话框有问题 - 您是否将其添加到 @NgModule.entryComponents?
【发布时间】:2017-05-22 00:42:41
【问题描述】:

我正在尝试关注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<DialogResultExampleDialog>) {}
}

在我的模块中我添加了

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

【问题讨论】:

    标签: angular angular-material


    【解决方案1】:

    Angular 9.0.0

    从 9.0.0 开始,Ivy 不再需要 entryComponents 属性。见deprecations guide

    Angular 9.0.0 >

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

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

    注意:在某些情况下,延迟加载的模块下的entryComponents 将不起作用,作为一种解决方法,请将它们放在您的app.module(root)中

    【讨论】:

    • 谢谢!到处找这个。在我的特殊情况下,我需要将组件添加到 declarations 以使工作正常
    • 每次当我想到 NgModule 时,就会出现类似的情况,让你想知道这个框架是否需要如此复杂。不过,至少错误消息很有帮助。
    • 如果你已经把它们放在里面了怎么办?为什么会说他们不是?
    • @SamAlexander 您的问题确实很宽泛,但您会很感激,但请大胆猜测;你会在你的延迟加载模块中使用它们吗?
    • 延迟加载模块中的对话框从 2.0.0-beta.2 开始工作
    【解决方案2】:

    我遇到了同样的问题,我在 EntryComponents 中有 dialogComponent,但它仍然无法正常工作。这就是我能够解决问题的方法。该链接指向之前已回答的帖子:

    https://stackoverflow.com/a/64224799/14385758

    【讨论】:

      【解决方案3】:

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

      创建一个服务,例如 DialogService,然后将您的对话功能移动到服务中,并将您的对话服务添加到您调用的组件中,如下代码所示:

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

      否则会出错

      【讨论】:

        【解决方案4】:

        @NgModule下需要使用entryComponents

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

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

        所以你的代码会是这样的

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

        【讨论】:

        • 呃...我有两个对话框,它们在其他方面是相同的,但一个我有一个指向它的测试路线。我删除了那条测试路线,果然……这条路线正在“帮助”我。 >:(
        • @Sunil Garg 我还有一个问题。我的对话框显示,但它会在 1 秒内自动关闭。请帮帮我。
        【解决方案5】:

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

        只需在此处添加:

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

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

        entryComponents?: Array&lt;Type&lt;any&gt;|any[]&gt;

        指定一个列表 定义此模块时应编译的组件。为了 这里列出的每个组件,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
        })
        

        【讨论】:

        • 与我的情况相同,但不起作用:它显示:错误:找不到 DialogConfirmComponent 的组件工厂。你把它添加到@NgModule.entryComponents 了吗?有什么想法吗?
        • 你需要将它插入到 ngAfterViewInit(来自@angular/core)
        【解决方案6】:

        在懒加载的情况下,只需要在懒加载模块中引入MatDialogModule。然后这个模块将能够使用自己导入的 MatDialogModule 渲染入口组件:

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

        【讨论】:

          【解决方案7】:

          您必须按照docs 中的规定将其添加到entryComponents

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

          这里是a full example 用于应用模块文件,其对话框定义为entryComponents

          【讨论】:

            【解决方案8】:

            虽然集成材质对话框可能,但我发现这种微不足道的功能的复杂性非常高。如果您尝试实现非平凡的功能,代码会变得更加复杂。

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

            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 documentation 易于理解且非常精确。

            【讨论】:

            • 只有在不需要动态创建的组件之前,您才不会面临主题启动问题。如果您尝试(即使使用primeng)创建使用动态组件创建的对话服务 - 您将面临完全相同的问题......
            【解决方案9】:

            如果您尝试在服务中使用MatDialog - 我们称之为'PopupService',并且该服务在一个模块中定义:

            @Injectable({ providedIn: 'root' })
            

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

            你必须:

            • PopupService 直接提供给打开对话框的组件 - 使用[ provide: PopupService ]。这允许它在组件中使用(通过 DI)MatDialog 实例。我认为调用open 的组件需要与本实例中的对话框组件位于同一模块中。
            • 将对话框组件移至您的 app.module(正如其他一些答案所说)
            • 在调用服务时传递matDialog 的引用。

            请原谅我的混乱回答,关键是 providedIn: 'root' 正在破坏事情,因为 MatDialog 需要搭载组件。

            【讨论】:

            • 这发生了!确实添加了你的服务来提供而不是查看入口组件,错误的错误信息!
            • 对我来说也发生了同样的事情,但我无法从这个答案中理解,哪一点是解决方案?还是三个都需要?
            • 我遇到了同样的问题
            【解决方案10】:

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

            【讨论】:

              【解决方案11】:

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

              【讨论】:

                猜你喜欢
                • 2017-06-16
                • 2018-04-09
                • 2019-11-06
                • 2016-10-17
                • 2021-08-22
                • 2019-01-30
                • 2017-12-24
                • 2016-11-23
                相关资源
                最近更新 更多