Hộp thoại vật liệu Angular2 có vấn đề - Bạn đã thêm nó vào @ NgModule.entryComponents?


232

Tôi cố gắng để làm theo các tài liệu trên https://material.angular.io/components/component/dialog nhưng tôi không thể hiểu tại sao nó có vấn đề dưới đây?

Tôi đã thêm vào dưới đây trên thành phần của tôi:

@Component({
  selector: 'dialog-result-example-dialog',
  templateUrl: './dialog-result-example-dialog.html',
})
export class DialogResultExampleDialog {
  constructor(public dialogRef: MdDialogRef<DialogResultExampleDialog>) {}
}

Trong mô-đun của tôi, tôi đã thêm

import { HomeComponent,DialogResultExampleDialog } from './home/home.component';

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

// ...

Tuy nhiên, tôi nhận được lỗi này ....

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

Câu trả lời:


603

Bạn cần thêm các thành phần được tạo động vào entryComponentsbên trong của bạn@NgModule

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

Lưu ý: Trong một số trường hợp entryComponentsdưới module lười nạp sẽ không hoạt động, như là một workaround đặt chúng trong của bạn app.module(root)


9
Cảm ơn! Đã tìm kiếm khắp nơi cho điều này. Trong trường hợp cụ thể của tôi, tôi cũng cần thêm thành phần này để declarationsmọi thứ hoạt động
Jasdeep Khalsa

95
Mỗi khi tôi cảm thấy như mình quay đầu lại với NgModule, một cái gì đó như thế này xuất hiện và khiến bạn tự hỏi liệu khuôn khổ này có cần phải phức tạp như vậy không. Ít nhất là các thông báo lỗi hữu ích mặc dù.
Daddywoodland

3
Điều gì nếu bạn đã có chúng trong đó? Tại sao nó lại nói họ không có?
Sam Alexander

1
@SamAlexander câu hỏi của bạn thực sự rộng khi bạn đánh giá cao nhưng lại đoán mò; Bạn có sử dụng chúng trong mô-đun tải lười biếng của bạn?
eko

1
các hộp thoại trong các mô-đun được tải lười biếng hoạt động kể từ 2.0.0-beta.2
charlie_pl

53

Bạn cần sử dụng entryComponentsdưới @NgModule.

Điều này là cho các thành phần được thêm động được thêm vào bằng cách sử dụng ViewContainerRef.createComponent(). Việc thêm chúng vào entryComponents sẽ cho trình biên dịch mẫu ngoại tuyến biên dịch chúng và tạo các nhà máy cho chúng.

Các thành phần được đăng ký trong cấu hình tuyến đường cũng được thêm tự động entryComponentsrouter-outletcũng sử dụng ViewContainerRef.createComponent()để thêm các thành phần được định tuyến vào DOM.

Vì vậy, mã của bạn sẽ như thế nào

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

Ugh ... Tôi có hai hộp thoại giống hệt nhau nhưng một hộp thoại tôi có một đường thử chỉ vào nó. Tôi đã xóa tuyến kiểm tra đó và chắc chắn rằng ... việc định tuyến đã "giúp" tôi. > :(
Tom

@Sunil Garg Tôi có một vấn đề khác. Hộp thoại của tôi hiển thị nhưng nó tự động đóng trong vòng 1 giây. Làm ơn giúp tôi.
Priyanka C

10

Điều này đang xảy ra bởi vì đây là một thành phần động và bạn đã không thêm nó vào entryComponentsbên dưới @NgModule.

Đơn giản chỉ cần thêm nó vào đó:

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

Nhìn vào cách nhóm Angular nói về entryComponents:

entryComponents?: Array<Type<any>|any[]>

Chỉ định danh sách các thành phần sẽ được biên dịch khi mô-đun này được xác định. Đối với mỗi thành phần được liệt kê ở đây, Angular sẽ tạo ra một ElementFactory và lưu trữ nó trong ElementFactoryResolver.

Ngoài ra, đây là danh sách các phương pháp @NgModulebao gồm entryComponents...

Như bạn có thể thấy, tất cả chúng đều là tùy chọn (nhìn vào các dấu hỏi), bao gồm cả entryComponentschấp nhận một loạt các thành phần:

@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
trường hợp tương tự với tôi và sẽ không hoạt động: nó hiển thị: Lỗi: Không tìm thấy nhà máy thành phần nào cho DialogConfirmComponent. Bạn đã thêm nó vào @ NgModule.entryComponents? Bất kỳ ý tưởng?
Nam Lê

Bạn cần chèn nó vào ngAfterViewInit (từ @ angular / core)
Patryk Panek

8

Nếu bạn đang cố gắng sử dụng MatDialogbên trong một dịch vụ - hãy gọi nó 'PopupService'và dịch vụ đó được xác định trong một mô-đun với:

@Injectable({ providedIn: 'root' })

sau đó nó có thể không hoạt động. Tôi đang sử dụng tải lười biếng, nhưng không chắc điều đó có liên quan hay không.

Bạn phải:

  • Cung cấp PopupServicetrực tiếp cho thành phần mở hộp thoại của bạn - bằng cách sử dụng [ provide: PopupService ]. Điều này cho phép nó sử dụng (với DI) MatDialogthể hiện trong thành phần. Tôi nghĩ rằng việc gọi thành phần opencần phải nằm trong cùng một mô-đun với thành phần hộp thoại trong trường hợp này.
  • Di chuyển thành phần hộp thoại lên app.module của bạn (như một số câu trả lời khác đã nói)
  • Vượt qua một tài liệu tham khảo matDialogkhi bạn gọi dịch vụ của bạn.

Xin lỗi, câu trả lời lộn xộn của tôi, vấn đề là nó providedIn: 'root'đang phá vỡ mọi thứ vì MatDialog cần cõng một thành phần.


điều này xảy ra! thực sự thêm dịch vụ của bạn để cung cấp thay vì nhìn vào entrycomponent, thông báo lỗi sai!
tibi

Điều tương tự cũng xảy ra với tôi, nhưng tôi không thể hiểu câu trả lời này, điểm nào là giải pháp? Hoặc cả 3 đều được yêu cầu?
mã hóa_idiot

Tôi đã có cùng một vấn đề
MJVM

4

Trong trường hợp lười tải, bạn chỉ cần nhập MatDialogModule trong mô-đun tải lười biếng. Sau đó, mô-đun này sẽ có thể kết xuất thành phần mục nhập với MatDialogModule được nhập riêng của nó :

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

1

Trong khi tích hợp hộp thoại vật liệu là có thể , tôi thấy rằng độ phức tạp cho một tính năng tầm thường như vậy là khá cao. Mã trở nên phức tạp hơn nếu bạn đang cố gắng đạt được một tính năng không tầm thường.

Vì lý do đó, tôi đã kết thúc việc sử dụng Hộp thoại PrimeNG , điều mà tôi thấy khá dễ sử dụng:

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 {}

Chỉ cần thêm hộp thoại của bạn vào html thành phần của bạn:

<m-dialog [isVisible]="true"> </m-dialog>

Tài liệu PrimeNG PrimeFaces rất dễ theo dõi và rất chính xác.


bạn không phải đối mặt với vấn đề khởi động chủ đề chỉ cho đến khi bạn không cần thành phần được tạo động. Nếu bạn thử (ngay cả với Primeng) tạo dịch vụ hộp thoại sử dụng tạo thành phần động - bạn sẽ gặp chính xác cùng một vấn đề ...
DicBrus

1

Bạn phải thêm nó vào entryComponents, như được chỉ định trong các tài liệu .

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

Dưới đây là một ví dụ đầy đủ cho một tệp mô-đun ứng dụng với hộp thoại được xác định là entryComponents.


0

Nếu bạn giống tôi và đang nhìn chằm chằm vào chủ đề này với suy nghĩ "Nhưng tôi không cố gắng thêm một thành phần, tôi đang cố gắng thêm một người bảo vệ / dịch vụ / đường ống, v.v." thì vấn đề có thể là bạn đã thêm loại sai vào đường dẫn định tuyến. Đó là những gì tôi đã làm. Tôi đã vô tình thêm một người bảo vệ vào thành phần: phần của một đường dẫn thay vì phần canActivate :. Tôi yêu IDE tự động hoàn thành nhưng bạn phải chậm lại một chút và chú ý. Nếu bạn hoàn toàn không thể tìm thấy nó, hãy thực hiện tìm kiếm toàn cầu cho tên mà nó đang phàn nàn và xem xét mọi cách sử dụng để đảm bảo bạn không bỏ sót tên nào.


0

Trong trường hợp của tôi, tôi đã thêm thành phần của mình vào khai báo và entryComponents và nhận được cùng một lỗi. Tôi cũng cần thêm MatDialogModule để nhập.


0

Nếu ai đó cần gọi Dialog từ các dịch vụ thì đây là cách giải quyết vấn đề. Tôi đồng ý với một số câu trả lời ở trên, câu trả lời của tôi là để gọi hộp thoại trong các dịch vụ nếu ai đó có thể gặp phải vấn đề trên.

Tạo một dịch vụ ví dụ DialogService sau đó di chuyển chức năng hộp thoại của bạn bên trong các dịch vụ và thêm dịch vụ hộp thoại của bạn vào thành phần bạn gọi như mã dưới đây:

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

nếu không thì bạn gặp lỗi

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.