La finestra di dialogo del materiale Angular2 presenta problemi: l'hai aggiunta a @ NgModule.entryComponents?


232

Sto cercando di seguire i documenti su https://material.angular.io/components/component/dialog ma non riesco a capire perché abbia il problema di seguito?

Ho aggiunto quanto segue sul mio componente:

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

Nel mio modulo ho aggiunto

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

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

// ...

Eppure ricevo questo errore ....

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

Risposte:


604

È necessario aggiungere componenti creati dinamicamente entryComponentsall'interno di@NgModule

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

Nota: in alcuni casi entryComponentscon i moduli caricati in modalità lazy non funzionerà, come soluzione alternativa inseriscili nel tuo app.module(root)


9
Grazie! Lo cercavo dappertutto. Nel mio caso particolare, dovevo anche aggiungere il componente al declarationsper far funzionare le cose
Jasdeep Khalsa,

95
Ogni volta che mi viene voglia di girare NgModule, mi viene in mente qualcosa del genere e ti fa chiedere se questo framework debba essere così complesso. Almeno i messaggi di errore sono utili.
Daddywoodland,

3
E se li avessi già dentro? perché direbbe che non sono?
Sam Alexander,

1
@SamAlexander la tua domanda è davvero ampia, come apprezzeresti ma facendo un'ipotesi selvaggia; li usi nel tuo modulo caricato pigro?
eko,

1
le finestre di dialogo nei moduli caricati pigri funzionano dalla 2.0.0-beta.2
charlie_pl

53

Devi usare entryComponentssotto @NgModule.

Questo è per i componenti aggiunti dinamicamente che vengono aggiunti usando ViewContainerRef.createComponent(). Aggiungendoli a entryComponents dice al compilatore di template offline di compilarli e creare fabbriche per loro.

I componenti registrati nelle configurazioni del percorso vengono aggiunti automaticamente entryComponentsanche perché router-outletutilizza anche ViewContainerRef.createComponent()per aggiungere componenti indirizzati al DOM.

Quindi il tuo codice sarà simile

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

Ugh ... ho avuto due dialoghi che erano identici, ma uno con un percorso di prova che lo indicava. Ho rimosso quel percorso di prova e sicuramente ... il routing mi stava "aiutando". > :(
Tom

@Sunil Garg Ho un altro problema. La mia finestra di dialogo mostra ma si chiude automaticamente entro 1 sec. Mi aiuti per favore.
Priyanka C

10

Ciò accade perché si tratta di un componente dinamico e non è stato aggiunto a entryComponentsunder@NgModule .

Aggiungilo semplicemente lì:

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

Guarda come parla la squadra angolareentryComponents :

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

Specifica un elenco di componenti che devono essere compilati quando viene definito questo modulo. Per ogni componente elencato qui, Angular creerà un ComponentFactory e lo memorizzerà nel ComponentFactoryResolver.

Inoltre, questo è l'elenco dei metodi per @NgModuleincludere entryComponents...

Come puoi vedere, tutti sono opzionali (guarda i punti interrogativi), inclusi quelli entryComponentsche accettano una serie di componenti:

@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
lo stesso caso con me e non funzionerà: mostra: Errore: nessuna factory di componente trovata per DialogConfirmComponent. L'hai aggiunto a @ NgModule.entryComponents? Qualche idea?
Nam Le

Devi inserirlo in ngAfterViewInit (da @ angular / core)
Patryk Panek

8

Se stai cercando di utilizzare MatDialogall'interno di un servizio, chiamiamolo 'PopupService'e quel servizio è definito in un modulo con:

@Injectable({ providedIn: 'root' })

quindi potrebbe non funzionare. Sto usando il caricamento lento, ma non sono sicuro che sia pertinente o meno.

Devi:

  • Fornisci PopupServicedirettamente al componente che apre la finestra di dialogo - usando [ provide: PopupService ]. Ciò consente di utilizzare (con DI) l' MatDialogistanza nel componente. Penso che il componente chiamaopen debba essere nello stesso modulo del componente della finestra di dialogo in questa istanza.
  • Sposta il componente della finestra di dialogo nel modulo app (come hanno già detto altre risposte)
  • Passa un riferimento per matDialogquando chiami il tuo servizio.

Scusa la mia risposta confusa, il punto è providedIn: 'root'che sta rompendo le cose perché MatDialog ha bisogno di recuperare un componente.


questo succede! anzi aggiungi il tuo servizio per fornire invece di guardare il messaggio di errore errato entrycomponent!
Tibi

Succede lo stesso per me, ma da questa risposta non sono riuscito a capire, quale punto è la soluzione? O tutti e 3 sono richiesti?
coding_idiot

Ho avuto lo stesso problema
MJVM il

4

In caso di caricamento lento, è sufficiente importare MatDialogModule nel modulo caricato lento. Quindi questo modulo sarà in grado di eseguire il rendering del componente di ingresso con il proprio MatDialogModule importato :

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

1

Mentre è possibile integrare la finestra di dialogo sui materiali , ho scoperto che la complessità di una caratteristica così banale è piuttosto elevata. Il codice diventa più complesso se stai cercando di ottenere funzionalità non banali.

Per questo motivo, ho finito per usare PrimeNG Dialog , che ho trovato abbastanza semplice da usare:

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

Aggiungi semplicemente la tua finestra di dialogo nel codice HTML del tuo componente:

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

PrimeNG La documentazione di PrimeFaces è facile da seguire e molto precisa.


non devi affrontare il problema dell'argomento iniziale solo finché non hai bisogno del componente dinamico creato. Se provi (anche con primeng) a creare dialogservice che utilizza la creazione dinamica di componenti, dovrai affrontare esattamente lo stesso problema ...
DicBrus,

1

È necessario aggiungerlo a entryComponents, come specificato nei documenti .

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

Ecco un esempio completo per un file del modulo app con una finestra di dialogo definita come entryComponents.


0

Se sei come me e stai fissando questa discussione pensando "Ma non sto provando ad aggiungere un componente, sto provando ad aggiungere un guard / service / pipe, ecc." quindi è probabile che tu abbia aggiunto il tipo sbagliato a un percorso di routing. Questo è quello che ho fatto. Ho accidentalmente aggiunto una protezione al componente: sezione di un percorso anziché canActivate: sezione. Adoro il completamento automatico IDE ma devi rallentare un po 'e prestare attenzione. Se non riesci assolutamente a trovarlo, fai una ricerca globale per il nome di cui si lamenta e osserva ogni utilizzo per assicurarti di non aver sbagliato con un nome.


0

Nel mio caso, ho aggiunto il mio componente a dichiarazioni e entryComponents e ho ottenuto gli stessi errori. Avevo anche bisogno di aggiungere MatDialogModule alle importazioni.


0

Se qualcuno ha bisogno di chiamare Dialog dai servizi qui è come risolvere il problema. Sono d'accordo con alcune delle risposte di cui sopra, la mia risposta è per chiamare il dialogo nei servizi se qualcuno può affrontare problemi.

Crea un servizio, ad esempio DialogService, quindi sposta la tua funzione di dialogo all'interno dei servizi e aggiungi il tuo servizio di dialogo nel componente che chiami come sotto il codice:

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

altrimenti ricevi un errore

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.