У диалогового окна материала 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
Tampa
источник

Ответы:

604

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

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

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

EKO
источник
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 должен отодвинуть компонент.

Simon_Weaver
источник
Это случилось! действительно добавьте свой сервис для предоставления вместо того, чтобы смотреть 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.

yuval.bl
источник
0

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

LeftOnTheMoon
источник
0

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

Dela
источник
0

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

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

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

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

MJVM
источник