У діалоговому вікні матеріалу 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до роботи, щоб роботи
почали

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

3
Що робити, якщо у вас їх уже було там? чому б це сказало, що вони не?
Сем Олександр

1
@SamAlexander ваше запитання дійсно широке, як ви оцінили б, але ви здогадуєтесь; ви використовуєте їх всередині вашого ледачого завантаженого модуля?
еко

1
діалоги в ледачих завантажених модулях працюють з 2.0.0-beta.2
charlie_pl

53

Вам потрібно використовувати entryComponentsпід @NgModule.

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

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

Тож ваш код буде таким

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

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

@Sunil Garg У мене є ще одна проблема. Моє діалогове шоу, але воно автоматично закривається протягом 1 сек. Будь ласка, допоможи мені.
Приянка C

10

Це відбувається, тому що це динамічний компонент, і ви не додавали його до entryComponentsпункту @NgModule.

Просто додайте його туди:

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

Подивіться, як говорить команда AngularentryComponents :

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 (від @ кутовий / ядра)
Patryk Pánek

8

Якщо ви намагаєтесь використовувати MatDialogвсередині сервісу - назвемо його, 'PopupService'і ця служба визначена в модулі з:

@Injectable({ providedIn: 'root' })

тоді це може не спрацювати. Я використовую ледачий навантаження, але не впевнений, це актуально чи ні.

Ти мусиш:

  • Надайте свій PopupServiceбезпосередньо компонент, який відкриває діалогове вікно - за допомогою [ provide: PopupService ]. Це дозволяє йому використовувати (з DI) MatDialogекземпляр у компоненті. Я думаю, що виклик компонента openповинен бути в тому ж модулі, що і діалоговий компонент у цьому випадку.
  • Перемістіть діалоговий компонент до свого модуля app (як сказано в деяких інших відповідях)
  • Передайте довідку, matDialogколи ви телефонуєте в службу.

Вибачте мою розгублену відповідь, справа в тому, що це те, providedIn: 'root'що ламає речі, тому що MatDialog потребує відмовки від компонента.


це трапляється! дійсно додайте свою послугу, щоб надати, а не дивитися на вхідний компонент, неправильне повідомлення про помилку!
tibi

Відбувається те ж саме для мене, але я не міг зрозуміти з цієї відповіді, який момент є рішенням? Або всі 3 потрібні?
coding_idiot

У мене був такий самий випуск
MJVM

4

У разі ледачого завантаження вам просто потрібно імпортувати MatDialogModule у модуль із ледачим завантаженням. Тоді цей модуль зможе надати вхідний компонент із власним імпортованим MatDialogModule :

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

1

Хоча інтеграція діалогу матеріалів можлива , я виявив, що складність такої тривіальної функції є досить високою. Код стає складнішим, якщо ви намагаєтеся досягти нетривіальних особливостей.

З цієї причини я застосував діалоговий вікно 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 просте у виконанні та дуже точна.


ви не стикаєтеся лише з проблемою для початківців тем, поки вам не потрібен динамічний створений компонент. Якщо ви спробуєте (навіть з primeng) створити діалоговий сервіс, який використовує створення динамічних компонентів, - ви зіткнетеся з точно такою ж проблемою ...
DicBrus

1

Ви повинні додати його entryComponents, як зазначено в документах .

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

Ось повний приклад файлу модуля програми з діалоговим вікном, визначеним як entryComponents.


0

Якщо ви схожі на мене, і дивитесь на цю нитку, думаючи: "Але я не намагаюся додати компонент, я намагаюся додати охорону / службу / трубу тощо". то ймовірно, що ви додали неправильний тип до шляху маршрутизації. Це я і зробив. Я випадково додав до компонента: розділ шляху замість розділу canActivate:. Я люблю автозаповнення IDE, але вам доведеться трохи сповільнити і звернути увагу. Якщо ви абсолютно не можете його знайти, зробіть глобальний пошук імені, на яке він скаржиться, і перегляньте кожне використання, щоб переконатися, що ви не проскочили ім’я.


0

У моєму випадку я додав свій компонент до декларацій та entryComponents і отримав однакові помилки. Мені також потрібно було додати MatDialogModule до імпорту.


0

Якщо комусь потрібно зателефонувати до Dialog із служб, ось як вирішити проблему. Я погоджуюсь з деякою вищезгаданою відповіддю, моя відповідь - це виклик діалогу в службах, якщо хтось може зіткнутися з проблемами.

Створіть службу, наприклад, 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.