example - El diálogo de material Angular2 tiene problemas. ¿Lo agregó a @ NgModule.entryComponents?
angular material navbar (9)
Debe agregarlo a
entryComponents
, como se especifica en los
docs
.
@NgModule({
imports: [
// ...
],
entryComponents: [
DialogInvokingComponent,
DialogResultExampleDialog
],
declarations: [
DialogInvokingComponent,
DialogResultExampleDialog
],
// ...
})
Aquí hay
un ejemplo completo
de un archivo de módulo de aplicación con un cuadro de diálogo definido como
entryComponents
.
Estoy tratando de seguir los documentos en https://material.angular.io/components/component/dialog pero no puedo entender por qué tiene el siguiente problema.
Agregué lo siguiente en mi componente:
@Component({
selector: ''dialog-result-example-dialog'',
templateUrl: ''./dialog-result-example-dialog.html'',
})
export class DialogResultExampleDialog {
constructor(public dialogRef: MdDialogRef<DialogResultExampleDialog>) {}
}
En mi módulo agregué
import { HomeComponent,DialogResultExampleDialog } from ''./home/home.component'';
@NgModule({
declarations: [
AppComponent,
LoginComponent,
DashboardComponent,
HomeComponent,
DialogResultExampleDialog
],
// ...
Sin embargo, recibo este error ...
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
En caso de carga diferida, solo necesita importar MatDialogModule en el módulo cargado diferido . Entonces este módulo podrá representar el componente de entrada con su propio MatDialogModule importado:
@NgModule({
imports:[
MatDialogModule
],
declarations: [
AppComponent,
LoginComponent,
DashboardComponent,
HomeComponent,
DialogResultExampleDialog
],
entryComponents: [DialogResultExampleDialog]
En mi caso, agregué mi componente a las declaraciones y entryComponents y obtuve los mismos errores. También necesitaba agregar MatDialogModule a las importaciones.
Esto está sucediendo porque este es un
componente dinámico
y no lo
entryComponents
a
entryComponents
en
@NgModule
.
Simplemente agréguelo allí:
@NgModule({
/* ----------------- */
entryComponents: [ DialogResultExampleDialog ] // <---- Add it here
Mire cómo el
equipo Angular
habla sobre los
entryComponents
de
entryComponents
:
entryComponents?: Array<Type<any>|any[]>
Especifica una lista de componentes que deben compilarse cuando se define este módulo. Para cada componente enumerado aquí, Angular creará un ComponentFactory y lo almacenará en ComponentFactoryResolver.
Además, esta es la lista de los métodos en
@NgModule
incluidos
entryComponents
...
Como puede ver, todos ellos son opcionales (mire los signos de interrogación), incluidos
entryComponents
que aceptan una variedad de componentes:
@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
})
Si bien es posible integrar el diálogo de material, descubrí que la complejidad de una característica tan trivial es bastante alta. El código se vuelve más complejo si está tratando de lograr características no triviales.
Por esa razón, terminé usando PrimeNG Dialog , que encontré bastante fácil de usar:
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 {}
Simplemente agregue su cuadro de diálogo en el html de su componente:
<m-dialog [isVisible]="true"> </m-dialog>
La documentación de PrimeNG PrimeFaces es fácil de seguir y muy precisa.
Si eres como yo y estás mirando este hilo pensando "Pero no estoy tratando de agregar un componente, estoy tratando de agregar un protector / servicio / tubería, etc." entonces es probable que haya agregado el tipo incorrecto a una ruta de enrutamiento. Eso es lo que hice. Accidentalmente agregué un protector al componente: sección de una ruta en lugar de canActivate: sección. Me encanta el autocompletado IDE, pero hay que reducir la velocidad un poco y prestar atención. Si no puede encontrarlo, realice una búsqueda global del nombre del que se queja y observe cada uso para asegurarse de que no se equivoca con un nombre.
Si está intentando usar
MatDialog
dentro de un servicio, llamémoslo
''PopupService''
y ese servicio se define en un módulo con:
@Injectable({ providedIn: ''root'' })
entonces puede que no funcione. Estoy usando carga diferida, pero no estoy seguro de si eso es relevante o no.
Tienes que:
-
Proporcione su
PopupService
directamente al componente que abre su diálogo, usando[ provide: PopupService ]
. Esto le permite usar (con DI) la instancia deMatDialog
en el componente. Creo que el componente que llama aopen
debe estar en el mismo módulo que el componente de diálogo en esta instancia. - Mueva el componente de diálogo hacia su app.module (como han dicho algunas otras respuestas)
-
Pase una referencia para
matDialog
cuando llame a su servicio.
Disculpe mi respuesta confusa,
el punto es que se
providedIn: ''root''
que se está rompiendo porque MatDialog necesita recuperar un componente.
entryComponents
agregar componentes creados dinámicamente a
entryComponents
dentro de su
@NgModule
@NgModule({
declarations: [
AppComponent,
LoginComponent,
DashboardComponent,
HomeComponent,
DialogResultExampleDialog
],
entryComponents: [DialogResultExampleDialog]
Nota:
En algunos casos,
entryComponents
en
módulos con carga diferida
no funcionará, como solución alternativa,
app.module
en su
app.module
(root)
entryComponents
usar
entryComponents
en
@NgModule
.
Esto es para componentes agregados dinámicamente que se agregan usando
ViewContainerRef.createComponent()
.
Agregarlos a entryComponents le dice al compilador de plantillas fuera de línea que los compile y cree fábricas para ellos.
Los componentes registrados en las configuraciones de ruta también se agregan automáticamente a
entryComponents
porque el
router-outlet
también usa
ViewContainerRef.createComponent()
para agregar componentes enrutados al DOM.
Entonces tu código será como
@NgModule({
declarations: [
AppComponent,
LoginComponent,
DashboardComponent,
HomeComponent,
DialogResultExampleDialog
],
entryComponents: [DialogResultExampleDialog]