กล่องโต้ตอบเนื้อหาของ 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(รูท)


9
ขอบคุณ! ถูกมองทุกที่สำหรับสิ่งนี้ ในกรณีเฉพาะของฉันฉันยังต้องเพิ่มองค์ประกอบในการที่declarationsจะได้รับสิ่งที่ทำงาน
Jasdeep Khalsa

95
ทุกครั้งที่ฉันรู้สึกเหมือนว่าฉันได้มุ่งหน้าไปรอบ ๆ NgModule บางอย่างเช่นนี้จะเกิดขึ้นและทำให้คุณสงสัยว่ากรอบนี้ต้องซับซ้อนไหม อย่างน้อยข้อความแสดงข้อผิดพลาดก็มีประโยชน์
daddywoodland

3
เกิดอะไรขึ้นถ้าคุณมีพวกเขาอยู่ในนั้น? ทำไมมันถึงบอกว่าพวกเขาไม่ได้?
แซมอเล็กซานเดอร์

1
@ SamAlexander คำถามของคุณกว้างจริง ๆ ตามที่คุณชื่นชม แต่การคาดเดาป่า; คุณจะใช้มันในโมดูลที่โหลดไม่ได้หรือไม่
eko

1
กล่องโต้ตอบในโมดูลที่โหลดแบบสันหลังยาวทำงานได้ตั้งแต่ 2.0.0-beta.2
charlie_pl

53

คุณจำเป็นต้องใช้ภายใต้entryComponents@NgModule

ViewContainerRef.createComponent()นี่คือสำหรับส่วนประกอบเพิ่มแบบไดนามิกที่มีการเพิ่มการใช้ การเพิ่มพวกเขาไปยังรายการส่วนประกอบบอกคอมไพเลอร์แม่แบบออฟไลน์เพื่อรวบรวมพวกเขาและสร้างโรงงานสำหรับพวกเขา

คอมโพเนนต์ที่ลงทะเบียนในการกำหนดค่าเส้นทางจะถูกเพิ่มโดยอัตโนมัติentryComponentsเช่นกันเนื่องจากrouter-outletใช้ViewContainerRef.createComponent()เพื่อเพิ่มส่วนประกอบที่กำหนดเส้นทางไปยัง DOM

ดังนั้นรหัสของคุณจะเป็นอย่างไร

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

อืม ... ฉันมีสองบทสนทนาที่เหมือนกัน แต่มีบททดสอบที่ชี้ไป ฉันลบเส้นทางการทดสอบนั้นแล้วและแน่นอนว่า ... การกำหนดเส้นทางนั้น "ช่วย" ฉัน > :(
Tom

@Sunil Garg ฉันมีปัญหาอื่น กล่องโต้ตอบของฉันแสดง แต่จะปิดโดยอัตโนมัติภายใน 1 วินาที โปรดช่วยฉันด้วย
Priyanka C

10

นี้เกิดขึ้นเพราะเป็นองค์ประกอบแบบไดนามิกและคุณไม่ได้เพิ่มเข้าไปภายใต้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
กรณีเดียวกันกับฉันและจะไม่ทำงาน: มันแสดงให้เห็น: ข้อผิดพลาด: ไม่พบส่วนประกอบโรงงานสำหรับ DialogConfirmComponent คุณเพิ่มไปยัง @ NgModule.entryComponents หรือไม่ ความคิดใด ๆ
Nam Le

คุณต้องใส่ลงใน ngAfterViewInit (จาก @ angular / core)
Patryk Panek

8

หากคุณกำลังพยายามที่จะใช้MatDialogภายในบริการ - ลองเรียกมัน'PopupService'และบริการที่กำหนดไว้ในโมดูลด้วย:

@Injectable({ providedIn: 'root' })

แล้วมันอาจไม่ทำงาน ฉันใช้การโหลดแบบขี้เกียจ แต่ไม่แน่ใจว่าเกี่ยวข้องหรือไม่

คุณต้อง:

  • ให้คุณPopupServiceโดยตรงกับส่วนประกอบที่จะเปิดกล่องโต้ตอบคุณ - [ provide: PopupService ]ใช้ สิ่งนี้ยอมให้มันใช้ (กับ DI) MatDialogอินสแตนซ์ในองค์ประกอบ ฉันคิดว่าการเรียกใช้คอมโพเนนต์openต้องอยู่ในโมดูลเดียวกันกับคอมโพเนนต์ไดอะล็อกในอินสแตนซ์นี้
  • ย้ายส่วนประกอบของกล่องโต้ตอบไปที่ app.module (ตามคำตอบอื่น ๆ )
  • ผ่านการอ้างอิงmatDialogเมื่อคุณเรียกใช้บริการของคุณ

ขออภัยคำตอบที่คลั่งไคล้ของฉันประเด็นที่มันprovidedIn: 'root'เป็นสิ่งที่แตกสลายเพราะ MatDialog ต้องการดึงลูกหมูออกจากส่วนประกอบ


สิ่งนี้เกิดขึ้น! แน่นอนเพิ่มบริการของคุณเพื่อให้แทนการดูรายการผิดพลาดผิดพลาด!
tibi

เกิดขึ้นแบบเดียวกันสำหรับฉัน แต่ฉันไม่เข้าใจจากคำตอบนี้ประเด็นคือทางออกอย่างไร หรือต้องการ 3 ทั้งหมด?
coding_idiot

ฉันมีปัญหาเดียวกัน
MJVM

4

ในกรณีของการโหลดแบบ lazy คุณเพียงแค่ต้องนำเข้า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
  ],
  // ...
})

ที่นี่คือ ตัวอย่างเต็มรูปแบบสำหรับไฟล์โมดูล app entryComponentsที่มีการโต้ตอบกำหนดให้เป็น


0

หากคุณเป็นเช่นฉันและกำลังจ้องมองที่หัวข้อนี้คิดว่า "แต่ฉันไม่ได้พยายามที่จะเพิ่มองค์ประกอบฉันพยายามที่จะเพิ่มยาม / บริการ / ท่อ ฯลฯ " ดังนั้นปัญหาน่าจะเป็นที่คุณได้เพิ่มประเภทผิดไปยังเส้นทางการกำหนดเส้นทาง นั่นคือสิ่งที่ฉันทำ ฉันบังเอิญเพิ่มตัวป้องกันลงในคอมโพเนนต์: ส่วนของเส้นทางแทนที่จะเป็นส่วน canActivate: ฉันชอบการเติมข้อความอัตโนมัติ IDE แต่คุณต้องชะลอตัวลงเล็กน้อยและให้ความสนใจ หากคุณไม่สามารถค้นหาได้ให้ค้นหาชื่อทั่วโลกเพื่อร้องเรียนและดูการใช้งานทุกครั้งเพื่อให้แน่ใจว่าคุณไม่ได้ใช้ชื่อ


0

ในกรณีของฉันฉันเพิ่มส่วนประกอบของฉันไปยังการประกาศและรายการส่วนประกอบและได้รับข้อผิดพลาดเดียวกัน ฉันยังต้องการเพิ่ม MatDialogModule เพื่อนำเข้า


0

หากมีคนต้องการโทรหาไดอะล็อกจากบริการที่นี่เป็นวิธีการแก้ปัญหา ฉันเห็นด้วยกับบางคำตอบข้างต้นคำตอบของฉันคือการโทรโต้ตอบในการบริการหากมีคนอาจประสบปัญหาใน

สร้างบริการเช่น DialogService จากนั้นย้ายฟังก์ชั่นการโต้ตอบของคุณภายในบริการและเพิ่มการบริการของคุณในส่วนที่คุณเรียกว่ารหัสด้านล่าง:

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

มิฉะนั้นคุณจะได้รับข้อผิดพลาด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.