У диалогового окна материала Angular2 есть проблемы - Вы добавили его в @ NgModule.entryComponents?


232

Я пытаюсь следовать документам на 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

Ответы:


604

Вы должны добавить динамически созданные компоненты entryComponentsвнутри@NgModule

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

Примечание: в некоторых случаях entryComponentsпод лениво загруженные модули не будут работать, как обходной путь, поместите их в свой app.module(root)


9
Спасибо! Искал везде это. В моем конкретном случае мне также нужно было добавить компонент, declarationsчтобы заставить вещи работать
Jasdeep Khalsa

95
Каждый раз, когда я чувствую себя так, как будто я начинаю думать о NgModule, возникает что-то подобное и заставляет задуматься, должна ли эта среда быть настолько сложной. По крайней мере, сообщения об ошибках полезны, хотя.
daddywoodland

3
Что, если они у вас уже были? с чего бы это сказать, что они не?
Сэм Александр

1
@ СамАлександр, твой вопрос очень широк, как ты бы оценил, но с дикой догадкой; вы используете их внутри вашего лениво загруженного модуля?
EKO

1
диалоги в лениво загруженных модулях работают с 2.0.0-бета.2
charlie_pl

53

Вы должны использовать entryComponentsпод @NgModule.

Это для динамически добавляемых компонентов, которые добавляются с помощью ViewContainerRef.createComponent(). Добавление их в entryComponents позволяет автономному компилятору шаблонов скомпилировать их и создать для них фабрики.

Компоненты, зарегистрированные в конфигурациях маршрутов, также добавляются автоматически, entryComponentsпоскольку router-outletтакже используются ViewContainerRef.createComponent()для добавления маршрутизируемых компонентов в DOM.

Так что ваш код будет похож

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

Тьфу ... У меня было два диалоговых окна, которые в остальном были идентичны, но у меня был тестовый маршрут, указывающий на него Я удалил этот тестовый маршрут и, конечно же ... маршрут помог мне. > :(
Том

@ Сунил Гарг У меня есть еще одна проблема. Мой диалог отображается, но он автоматически закрывается в течение 1 секунды. Пожалуйста, помогите мне.
Приянка C

10

Это происходит потому, что это динамический компонент, и вы не добавили его в entryComponentsunder @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
тот же случай со мной и не будет работать: он показывает: Ошибка: не найдена фабрика компонентов для DialogConfirmComponent. Вы добавили его в @ NgModule.entryComponents? Любая идея?
Нам Ле

Вам нужно вставить его в ngAfterViewInit (из @ angular / core)
Патрик Панек

8

Если вы пытаетесь использовать MatDialogвнутри службы - давайте назовем ее, 'PopupService'и эта служба определена в модуле с:

@Injectable({ providedIn: 'root' })

тогда это может не сработать. Я использую отложенную загрузку, но не уверен, что это актуально или нет.

Ты должен:

  • Предоставьте свой PopupServiceнепосредственно компоненту, который открывает ваш диалог - используя [ provide: PopupService ]. Это позволяет ему использовать (с DI) MatDialogэкземпляр в компоненте. Я думаю, что компонент вызова openдолжен быть в том же модуле, что и компонент диалога в этом случае.
  • Переместите компонент диалога вверх в ваш app.module (как сказали некоторые другие ответы)
  • Передайте справку, matDialogкогда вы звоните в свой сервис.

Извините за мой беспорядочный ответ, смысл в том, что это то, providedIn: 'root'что ломает вещи, потому что MatDialog должен отодвинуть компонент.


Это случилось! действительно добавьте свой сервис для предоставления вместо того, чтобы смотреть entrycomponent, неправильное сообщение об ошибке!
Тиби

Случалось то же самое для меня, но я не мог понять из этого ответа, какой пункт является решением? Или все 3 обязательны?
coding_idiot

У меня была такая же проблема
MJVM

4

В случае отложенной загрузки, вам просто нужно импортировать MatDialogModule в загруженный модуль с отложенной загрузкой. Затем этот модуль сможет визуализировать компонент ввода с собственным импортированным MatDialogModule :

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

1

Хотя интеграция материалов диалога возможна , я обнаружил, что сложность такой тривиальной функции довольно высока. Код становится более сложным, если вы пытаетесь достичь нетривиальных функций.

По этой причине я использовал 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 проста в использовании и очень точна.


Вы не столкнетесь с проблемой начала темы, пока вам не понадобится динамически созданный компонент. Если вы попытаетесь (даже с primeng) создать диалоговую службу, которая использует динамическое создание компонентов - вы столкнетесь с точно такой же проблемой ...
DicBrus

1

Вы должны добавить его entryComponents, как указано в документации .

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

Вот полный пример файла модуля приложения с диалоговым окном, определенным как entryComponents.


0

Если вы похожи на меня и смотрите на эту тему, думая: «Но я не пытаюсь добавить компонент, я пытаюсь добавить охрану / службу / канал и т. Д.» тогда проблема, вероятно, в том, что вы добавили неправильный тип в маршрутный путь. Это то, что я сделал. Я случайно добавил элемент защиты: раздел пути вместо раздела canActivate :. Я люблю автозаполнение IDE, но вы должны немного замедлиться и обратить внимание. Если вы абсолютно не можете его найти, выполните глобальный поиск имени, на которое он жалуется, и посмотрите на каждое использование, чтобы убедиться, что вы не ошиблись с именем.


0

В моем случае я добавил свой компонент в объявлений и entryComponents и получил те же ошибки. Мне также нужно было добавить MatDialogModule для импорта.


0

Если кому-то нужно позвонить в «Диалог» из сервисов, вот как решить проблему. Я согласен с некоторыми из приведенных выше ответов, мой ответ для вызова диалога в службах, если у кого-то могут возникнуть проблемы.

Создайте сервис, например, DialogService, затем переместите свою диалоговую функцию внутри сервисов и добавьте свой диалог-сервис в компонент, который вы вызываете, как показано ниже:

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

в противном случае вы получите ошибку

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.