Angular2材质对话框有问题 - 您是否将其添加到@ NgModule.entryComponents?

时间:2017-01-07 08:34:30

标签: angular angular-material

我正在尝试关注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

11 个答案:

答案 0 :(得分:526)

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

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

注意:在某些情况下,延迟加载的模块下的entryComponents将无效,因为解决方法会将它们放入app.module(root)

答案 1 :(得分:45)

您需要在entryComponents下使用@NgModule

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

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

所以你的代码就像

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

答案 2 :(得分:9)

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

只需将其添加到那里:

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

了解 Angular团队如何讨论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
})

答案 3 :(得分:3)

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

@Injectable({ providedIn: 'root' })

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

您必须:

  • 使用PopupService[ provide: PopupService ]直接提供给打开对话框的组件。这使它可以(通过DI)使用组件中的MatDialog实例。我认为在这种情况下,调用open的组件必须与对话框组件位于同一模块中。
  • 将对话框组件移至您的app.module(如其他答案所述)
  • 调用服务时传递matDialog的引用。

不好意思,关键是providedIn: 'root'会破坏一切,因为MatDialog需要附带组件。

答案 4 :(得分:2)

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

出于这个原因,我最终使用了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易于遵循且非常精确。

答案 5 :(得分:0)

如果你像我一样,并且正在盯着这个线程思考“但我不想添加组件,我正在尝试添加一个警卫/服务/管道等”那么问题很可能是您在路由路径中添加了错误的类型。这就是我做的。我不小心为组件添加了一个警卫:路径的一部分而不是canActivate:部分。我喜欢IDE自动完成功能,但你必须放慢速度并注意。如果您无法找到它,请在全球范围内搜索它所抱怨的名称,并查看每个用法,以确保您没有使用名称。

答案 6 :(得分:0)

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

答案 7 :(得分:0)

在延迟加载的情况下,您只需要在延迟加载的模块中导入 MatDialogModule 。然后,该模块将能够使用其自己导入的 MatDialogModule 渲染输入组件:

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

答案 8 :(得分:0)

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

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

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

答案 9 :(得分:0)

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

创建一个服务(例如DialogService),然后将对话框函数移到服务内部,然后在调用的组件中添加dialogservice,如下代码所示:

game_date = datetime.strptime(game.date, "%Y-%m-%d").date()
if game_date <= today :

    print(game_date)
    print(game.result)
    df = game.boxscore.dataframe
    r = game.boxscore('Timo Meier').dataframe
    print(r)

否则您将得到错误

答案 10 :(得分:0)

我遇到了同样的问题,我在EntryComponents中有dialogComponent,但仍然无法正常工作。这就是我解决问题的方式。链接在这里是先前答复的帖子:

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