La boîte de dialogue des matériaux Angular2 a des problèmes - L'avez-vous ajoutée à @ NgModule.entryComponents?

232

J'essaie de suivre les documents sur https://material.angular.io/components/component/dialog mais je ne comprends pas pourquoi il a le problème ci-dessous?

J'ai ajouté ci-dessous sur mon composant:

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

Dans mon module j'ai ajouté

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

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

// ...

Pourtant, je reçois cette erreur ....

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
la source

Réponses:

604

Vous devez ajouter des composants créés dynamiquement à l' entryComponentsintérieur de votre@NgModule

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

Remarque: Dans certains cas , entryComponentssous les modules chargés paresseux ne fonctionnera pas, comme solution de contournement les mettre dans votre app.module(racine)

eko
la source
9
Merci! Je cherchais partout pour ça. Dans mon cas particulier, j'ai également dû ajouter le composant à declarationspour que les choses fonctionnent
Jasdeep Khalsa
95
Chaque fois que je me sens comme si je me fais une idée de NgModule, quelque chose comme ça arrive et vous fait vous demander si ce cadre doit être si complexe. Au moins, les messages d'erreur sont utiles.
daddywoodland
3
Et si vous les aviez déjà là-dedans? pourquoi dirait-on qu'ils ne sont pas?
Sam Alexander
1
@SamAlexander, votre question est très large, comme vous l'apprécieriez, mais en prenant une supposition folle; les utilisez-vous dans votre module chargé paresseux?
eko
1
les boîtes de dialogue dans les modules chargés paresseux fonctionnent à partir de 2.0.0-beta.2
charlie_pl
53

Vous devez utiliser entryComponentssous@NgModule .

C'est pour les composants ajoutés dynamiquement qui sont ajoutés à l'aide ViewContainerRef.createComponent() . En les ajoutant à entryComponents, le compilateur de modèles hors ligne doit les compiler et créer des usines pour eux.

Les composants enregistrés dans les configurations d'itinéraire sont également ajoutés automatiquement entryComponentscar ils router-outletutilisent égalementViewContainerRef.createComponent() d'ajouter des composants routés au DOM.

Ainsi, votre code sera comme

@NgModule({
  declarations: [
    AppComponent,
    LoginComponent,
    DashboardComponent,
    HomeComponent,
    DialogResultExampleDialog        
  ],
  entryComponents: [DialogResultExampleDialog]
Sunil Garg
la source
Ugh ... J'ai eu deux dialogues qui étaient par ailleurs identiques, mais un que j'avais un itinéraire de test pointant vers elle. J'ai supprimé cette route de test et bien sûr ... le routage m'aidait ". > :(
Tom
@Sunil Garg J'ai un autre problème. Ma boîte de dialogue s'affiche mais se ferme automatiquement en 1 seconde. Aidez-moi, s'il vous plaît.
Priyanka C
10

Cela se produit car il s'agit d'un composant dynamique et vous ne l'avez pas ajouté à entryComponentssous@NgModule .

Ajoutez-le simplement ici:

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

Regardez comment l' équipe Angular parle de entryComponents:

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

Spécifie une liste de composants qui doivent être compilés lorsque ce module est défini. Pour chaque composant répertorié ici, Angular créera un ComponentFactory et le stockera dans ComponentFactoryResolver.

Aussi, voici la liste des méthodes pour @NgModuleinclure entryComponents...

Comme vous pouvez le voir, tous sont facultatifs (regardez les points d'interrogation), y compris ceux entryComponentsqui acceptent un tableau de composants:

@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
la source
3
même cas avec moi et ne fonctionne pas: il montre: Erreur: Aucune fabrique de composants trouvée pour DialogConfirmComponent. L'avez-vous ajouté à @ NgModule.entryComponents? Une idée?
Nam Le
Vous devez l'insérer dans ngAfterViewInit (de @ angular / core)
Patryk Panek
8

Si vous essayez d'utiliser à l' MatDialogintérieur d'un service - appelons-le 'PopupService'et ce service est défini dans un module avec:

@Injectable({ providedIn: 'root' })

alors cela peut ne pas fonctionner. J'utilise le chargement paresseux, mais je ne sais pas si c'est pertinent ou non.

Vous devez:

  • Fournissez votre PopupServicedirectement au composant qui ouvre votre boîte de dialogue - en utilisant [ provide: PopupService ]. Cela lui permet d'utiliser (avec DI) l' MatDialoginstance dans le composant. Je pense que le composant appelleopen doit être dans le même module que le composant de dialogue dans cette instance.
  • Déplacez le composant de dialogue vers votre module d'application (comme l'ont dit d'autres réponses)
  • Passez une référence matDialoglorsque vous appelez votre service.

Excusez ma réponse confuse, le fait étant providedIn: 'root'que c'est la rupture qui fait que MatDialog a besoin de superposer un composant.

Simon_Weaver
la source
ça arrive! ajoutez en effet votre service à fournir au lieu de regarder composant d'entrée, mauvais message d'erreur!
tibi
C'est pareil pour moi, mais je ne pouvais pas comprendre de cette réponse, quel point est la solution? Ou les 3 sont nécessaires?
coding_idiot
J'ai eu le même problème
MJVM
4

En cas de chargement paresseux, il vous suffit d'importer MatDialogModule dans le module chargé paresseux. Ensuite, ce module pourra rendre le composant d'entrée avec son propre MatDialogModule importé :

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

Bien qu'il soit possible d' intégrer un dialogue sur les matériaux , j'ai trouvé que la complexité d'une fonctionnalité aussi triviale est assez élevée. Le code devient plus complexe si vous essayez de réaliser des fonctionnalités non triviales.

Pour cette raison, j'ai fini par utiliser PrimeNG Dialog , que j'ai trouvé assez simple à utiliser:

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

Ajoutez simplement votre dialogue dans le html de votre composant:

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

La documentation PrimeNG PrimeFaces est facile à suivre et très précise.

Menelaos Kotsollaris
la source
vous ne rencontrez pas de problème de démarrage de sujet uniquement jusqu'à ce que vous n'ayez pas besoin d'un composant créé dynamiquement. Si vous essayez (même avec primeng) de créer un service de dialogue qui utilise la création de composants dynamiques - vous serez confronté exactement au même problème ...
DicBrus
1

Vous devez l'ajouter à entryComponents, comme spécifié dans les documents .

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

Voici un exemple complet pour un fichier de module d'application avec une boîte de dialogue définie comme entryComponents.

yuval.bl
la source
0

Si vous êtes comme moi et que vous regardez ce fil en pensant "Mais je n'essaie pas d'ajouter un composant, j'essaie d'ajouter un garde / service / tuyau, etc." alors le problème est probable que vous avez ajouté le mauvais type à un chemin de routage. Voilà ce que j'ai fait. J'ai accidentellement ajouté un garde au composant: section d'un chemin au lieu de la section canActivate :. J'adore la saisie semi-automatique IDE mais vous devez ralentir un peu et faire attention. Si vous ne le trouvez absolument pas, faites une recherche globale pour le nom dont il se plaint et examinez chaque utilisation pour vous assurer que vous n'avez pas glissé avec un nom.

LeftOnTheMoon
la source
0

Dans mon cas, j'ai ajouté mon composant aux déclarations et entryComponents et j'ai eu les mêmes erreurs. J'ai également dû ajouter MatDialogModule aux importations.

Dela
la source
0

Si quelqu'un doit appeler Dialog à partir des services, voici comment résoudre le problème. Je suis d'accord avec certaines des réponses ci-dessus, ma réponse est d'appeler le dialogue dans les services si quelqu'un peut rencontrer des problèmes.

Créez un service par exemple DialogService puis déplacez votre fonction de dialogue à l'intérieur des services et ajoutez votre dialogueservice dans le composant que vous appelez comme ci-dessous:

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

sinon vous obtenez une erreur

MJVM
la source