Angular2-Materialdialog hat Probleme - Haben Sie ihn zu @ NgModule.entryComponents hinzugefügt?

232

Ich versuche, den Dokumenten unter https://material.angular.io/components/component/dialog zu folgen , kann aber nicht verstehen, warum das folgende Problem vorliegt.

Ich habe Folgendes zu meiner Komponente hinzugefügt:

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

In meinem Modul habe ich hinzugefügt

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

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

// ...

Trotzdem bekomme ich diesen Fehler ....

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
quelle

Antworten:

603

Sie müssen dynamisch erstellte Komponenten zu entryComponentsIhrem hinzufügen@NgModule

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

Hinweis: In einigen Fällen funktionieren entryComponentsunter faul geladenen Modulen nicht, da eine Problemumgehung sie in Ihre app.module(root)

eko
quelle
9
Vielen Dank! Habe überall danach gesucht. In meinem speziellen Fall musste ich auch die Komponente hinzufügen declarations, um die Dinge zum
Laufen
95
Jedes Mal, wenn ich Lust habe, mich mit NgModule zu beschäftigen, taucht so etwas auf und Sie fragen sich, ob dieses Framework so komplex sein muss. Zumindest die Fehlermeldungen sind hilfreich.
Daddywoodland
3
Was wäre, wenn Sie sie bereits dort hätten? warum sollte es sagen, dass sie nicht sind?
Sam Alexander
1
@SamAlexander Ihre Frage ist wirklich weit gefasst, wie Sie schätzen würden, aber eine wilde Vermutung anstellen; Verwenden Sie sie in Ihrem faul geladenen Modul?
Eko
1
Dialoge in faul geladenen Modulen funktionieren ab 2.0.0-beta.2
charlie_pl
53

Sie müssen entryComponentsunter verwenden @NgModule.

Dies gilt für dynamisch hinzugefügte Komponenten, die mit hinzugefügt werden ViewContainerRef.createComponent(). Durch Hinzufügen zu entryComponents wird der Offline-Vorlagen-Compiler angewiesen, sie zu kompilieren und Fabriken für sie zu erstellen.

Die in Routenkonfigurationen registrierten Komponenten werden ebenfalls automatisch hinzugefügt, entryComponentsda sie router-outletauch ViewContainerRef.createComponent()zum Hinzufügen gerouteter Komponenten zum DOM verwendet werden.

Ihr Code wird also so sein

@NgModule({
  declarations: [
    AppComponent,
    LoginComponent,
    DashboardComponent,
    HomeComponent,
    DialogResultExampleDialog        
  ],
  entryComponents: [DialogResultExampleDialog]
Sunil Garg
quelle
Ugh ... Ich hatte zwei Dialoge, die ansonsten identisch waren, aber einen, auf den ich eine Testroute zeigte. Ich habe diese Testroute entfernt und sicher genug ... das Routing hat mir "geholfen". > :(
Tom
@ Sunil Garg Ich habe ein anderes Problem. Mein Dialog wird angezeigt, aber es wird automatisch innerhalb von 1 Sekunde geschlossen. Bitte hilf mir.
Priyanka C
10

Dies geschieht , weil dies eine ist dynamische Komponente , und Sie haben es nicht hinzuzufügen entryComponentsunter @NgModule.

Fügen Sie es einfach dort hinzu:

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

Sehen Sie sich an, wie das Angular-Team darüber spricht entryComponents:

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

Gibt eine Liste der Komponenten an, die bei der Definition dieses Moduls kompiliert werden sollen. Für jede hier aufgeführte Komponente erstellt Angular eine ComponentFactory und speichert sie im ComponentFactoryResolver.

Dies ist auch die Liste der Methoden zum @NgModuleEinschließen von entryComponents...

Wie Sie sehen können, sind alle optional (siehe Fragezeichen), einschließlich entryComponentsderer, die eine Reihe von Komponenten akzeptieren:

@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
})
Alireza
quelle
3
Der gleiche Fall bei mir und wird nicht funktionieren: Es zeigt: Fehler: Keine Komponentenfactory für DialogConfirmComponent gefunden. Haben Sie es zu @ NgModule.entryComponents hinzugefügt? Irgendeine Idee?
Nam Le
Sie müssen es in ngAfterViewInit (von @ angle / core) einfügen
Patryk Panek
8

Wenn Sie versuchen, MatDialoginnerhalb eines Dienstes zu verwenden, rufen wir ihn auf 'PopupService'und dieser Dienst wird in einem Modul definiert mit:

@Injectable({ providedIn: 'root' })

dann kann es nicht funktionieren. Ich verwende Lazy Loading, bin mir aber nicht sicher, ob das relevant ist oder nicht.

Sie müssen:

  • Stellen Sie Ihre PopupServicedirekt der Komponente zur Verfügung, die Ihren Dialog öffnet - mit [ provide: PopupService ]. Dies ermöglicht es ihm, (mit DI) die MatDialogInstanz in der Komponente zu verwenden. Ich denke, der Komponentenaufruf openmuss sich in diesem Fall im selben Modul wie die Dialogkomponente befinden.
  • Verschieben Sie die Dialogkomponente nach oben in Ihr app.module (wie in einigen anderen Antworten angegeben).
  • Übergeben Sie eine Referenz, matDialogwenn Sie Ihren Dienst anrufen.

Entschuldigen Sie meine durcheinandergebrachte Antwort. Der Punkt ist, providedIn: 'root'dass die Dinge kaputt gehen, weil MatDialog eine Komponente huckepack nehmen muss.

Simon_Weaver
quelle
das passiert! Fügen Sie in der Tat Ihren Dienst hinzu, um eine falsche Fehlermeldung bereitzustellen, anstatt auf die Eingabekomponente zu schauen!
Tibi
Das gleiche passiert für mich, aber ich konnte aus dieser Antwort nicht verstehen, welcher Punkt ist die Lösung? Oder sind alle 3 erforderlich?
Coding_idiot
Ich hatte das gleiche Problem
MJVM
4

Im Falle eines verzögerten Ladens müssen Sie nur MatDialogModule in ein verzögert geladenes Modul importieren . Dann kann dieses Modul die Eintragskomponente mit seinem eigenen importierten MatDialogModule rendern :

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

Während die Integration von Materialdialogen möglich ist , habe ich festgestellt, dass die Komplexität für solch ein triviales Feature ziemlich hoch ist. Der Code wird komplexer, wenn Sie versuchen, nicht triviale Funktionen zu erzielen.

Aus diesem Grund habe ich schließlich PrimeNG Dialog verwendet , was ich als ziemlich einfach empfand :

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

Fügen Sie einfach Ihren Dialog in das HTML Ihrer Komponente ein:

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

Die PrimeNG PrimeFaces-Dokumentation ist einfach zu befolgen und sehr präzise.

Menelaos Kotsollaris
quelle
Sie haben nur dann Probleme mit dem Thema-Starter, wenn Sie keine dynamisch erstellte Komponente benötigen. Wenn Sie versuchen (auch mit primeng), einen Dialogdienst zu erstellen, der die dynamische Komponentenerstellung verwendet, werden Sie genau das gleiche Problem haben ...
DicBrus
1

Sie müssen es hinzufügen entryComponents, wie in den Dokumenten angegeben .

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

Hier ist ein vollständiges Beispiel für eine App-Moduldatei mit einem Dialogfeld, das als definiert ist entryComponents.

yuval.bl
quelle
0

Wenn Sie wie ich sind und auf diesen Thread starren und denken: "Aber ich versuche nicht, eine Komponente hinzuzufügen, ich versuche, einen Schutz / Service / Rohr usw. hinzuzufügen." In diesem Fall ist es wahrscheinlich, dass Sie einem Routing-Pfad den falschen Typ hinzugefügt haben. Das habe ich getan. Ich habe versehentlich einen Schutz für den Abschnitt component: eines Pfads anstelle des Abschnitts canActivate: hinzugefügt. Ich liebe die automatische Vervollständigung von IDE, aber Sie müssen etwas langsamer fahren und aufpassen. Wenn Sie es absolut nicht finden können, führen Sie eine globale Suche nach dem Namen durch, über den es sich beschwert, und überprüfen Sie jede Verwendung, um sicherzustellen, dass Sie nicht mit einem Namen verrutscht sind.

LeftOnTheMoon
quelle
0

In meinem Fall habe ich meine Komponente zu Deklarationen und entryComponents hinzugefügt und die gleichen Fehler erhalten. Ich musste auch MatDialogModule zu Importen hinzufügen.

Dela
quelle
0

Wenn jemand Dialog von den Diensten aus aufrufen muss, können Sie das Problem hier lösen. Ich bin mit einigen der oben genannten Antworten einverstanden. Meine Antwort besteht darin, den Dialog in Diensten aufzurufen, wenn jemand auf Probleme stößt.

Erstellen Sie einen Dienst, zum Beispiel DialogService, verschieben Sie dann Ihre Dialogfunktion innerhalb der Dienste und fügen Sie Ihren Dialogdienst in der Komponente hinzu, die Sie wie folgt aufrufen:

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

Andernfalls erhalten Sie eine Fehlermeldung

MJVM
quelle