Components: Dialog demo - error No component factory found for

Created on 13 Oct 2016  路  46Comments  路  Source: angular/components

I use https://github.com/angular/material2/blob/master/src/demo-app/dialog/ for my project(create by angular-cli) and get this error.
error_handler.js:45 EXCEPTION: No component factory found for JazzDialogErrorHandler.handleError @ error_handler.js:45next @ application_ref.js:273schedulerFn @ async.js:82SafeSubscriber.__tryOrUnsub @ Subscriber.js:223SafeSubscriber.next @ Subscriber.js:172Subscriber._next @ Subscriber.js:125Subscriber.next @ Subscriber.js:89Subject.next @ Subject.js:55EventEmitter.emit @ async.js:74onError @ ng_zone.js:120onHandleError @ ng_zone_impl.js:64ZoneDelegate.handleError @ zone.js:207Zone.runGuarded @ zone.js:113NgZoneImpl.runInnerGuarded @ ng_zone_impl.js:72NgZone.runGuarded @ ng_zone.js:236outsideHandler @ dom_events.js:26ZoneDelegate.invokeTask @ zone.js:236Zone.runTask @ zone.js:136ZoneTask.invoke @ zone.js:304 error_handler.js:50 ORIGINAL STACKTRACE:ErrorHandler.handleError @ error_handler.js:50next @ application_ref.js:273schedulerFn @ async.js:82SafeSubscriber.__tryOrUnsub @ Subscriber.js:223SafeSubscriber.next @ Subscriber.js:172Subscriber._next @ Subscriber.js:125Subscriber.next @ Subscriber.js:89Subject.next @ Subject.js:55EventEmitter.emit @ async.js:74onError @ ng_zone.js:120onHandleError @ ng_zone_impl.js:64ZoneDelegate.handleError @ zone.js:207Zone.runGuarded @ zone.js:113NgZoneImpl.runInnerGuarded @ ng_zone_impl.js:72NgZone.runGuarded @ ng_zone.js:236outsideHandler @ dom_events.js:26ZoneDelegate.invokeTask @ zone.js:236Zone.runTask @ zone.js:136ZoneTask.invoke @ zone.js:304 error_handler.js:51 Error: No component factory found for JazzDialog at NoComponentFactoryError.Error (native) at NoComponentFactoryError.BaseError [as constructor] (http://localhost:4200/main.bundle.js:7143:34) at new NoComponentFactoryError (http://localhost:4200/main.bundle.js:20178:16) at _NullComponentFactoryResolver.resolveComponentFactory (http://localhost:4200/main.bundle.js:20187:15) at NgModuleInjector.CodegenComponentFactoryResolver.resolveComponentFactory (http://localhost:4200/main.bundle.js:20212:35) at PortalHostDirective.attachComponentPortal (http://localhost:4200/main.bundle.js:33774:63) at MdDialogContainer.attachComponentPortal (http://localhost:4200/main.bundle.js:49832:45) at MdDialog._attachDialogContent (http://localhost:4200/main.bundle.js:70085:42) at MdDialog.open (http://localhost:4200/main.bundle.js:70042:21) at HomeComponent.open (http://localhost:4200/main.bundle.js:77695:38)ErrorHandler.handleError @ error_handler.js:51next @ application_ref.js:273schedulerFn @ async.js:82SafeSubscriber.__tryOrUnsub @ Subscriber.js:223SafeSubscriber.next @ Subscriber.js:172Subscriber._next @ Subscriber.js:125Subscriber.next @ Subscriber.js:89Subject.next @ Subject.js:55EventEmitter.emit @ async.js:74onError @ ng_zone.js:120onHandleError @ ng_zone_impl.js:64ZoneDelegate.handleError @ zone.js:207Zone.runGuarded @ zone.js:113NgZoneImpl.runInnerGuarded @ ng_zone_impl.js:72NgZone.runGuarded @ ng_zone.js:236outsideHandler @ dom_events.js:26ZoneDelegate.invokeTask @ zone.js:236Zone.runTask @ zone.js:136ZoneTask.invoke @ zone.js:304 zone.js:140 Uncaught Error: No component factory found for JazzDialogZone.runTask @ zone.js:140ZoneTask.invoke @ zone.js:304

Who can help me fix it, please

Most helpful comment

Share some code, make also sure that the component you're trying to open is defined as entry in your NgModule's entryComponents: []

All 46 comments

Share some code, make also sure that the component you're trying to open is defined as entry in your NgModule's entryComponents: []

Correct. What @msegers said. Placing components into the entryComponents portion of the NgModule declaration will allow Angular to compile those components into component factories and therefore allow the component resolver to add them to the internal map used for component resolution.

Same issue here. The code I am trying is essentially the same demo "JazzDialog" at material2/src/demo-app/dialog/ on GitHub.

We are on RC5. Will this only work with RC-final?

I did it. Edit my app.module.ts like https://github.com/angular/material2/blob/master/src/demo-app/demo-app-module.ts

entryComponents: [ JazzDialog, ]

and in my component need show dialog, i edit it like https://github.com/angular/material2/tree/master/src/demo-app/dialog.

That seemed to work! Thanks!

OK, close it

FYI, it has to be the main module, at least for me, it wouldn't work in a sub-module.

@lozthiensu This issue came up again... I worked before without doing this and now with new angular updates this broke again or is this supposed to be intended use.

I also had issues with the error "No component factory". I tried declaring the component in both the same module as the parent, as well as the AppModule. Same error in both cases.

The demo on material.angular.io declares the dialog component in the same file. Maybe it's an issue for angular if you declare the component in a separate file, as you would do with any other component.

@lozthiensu you should reopen this issue because there is not clear documentation on this.

Also having this issue. Not sure how I'm supposed to get this to work in a lazy-loaded module. If i put the component in the lazy-loaded modules entryComponents array i still get:

No component factory found for xxxComponent. Did you add it to @NgModule.entryComponents

_angular-cli: 1.0.0-beta.26_
_Angular 2.4.5_
Confirmed, you cannot create a Dialog Component in a lazy-loaded module (Router loadChildren string value).

Is this an Angular project issue, or should this material2 issue be re-opened?

SOLVED with lazy loaded module:

i have done this, i have added GenerateApiKeyComponent (dialog component) to delcarations array and in entryComponent array and its working fine. its opening dialog.

 declarations: [
    AdminComponent,
    ProjectsComponent,
    ProjectComponent,
    ProjectDetailsComponent,
    DashboardComponent,
    GenerateApiKeyComponent
  ],
  entryComponents: [
    GenerateApiKeyComponent
  ],
  providers: [ProjectService]
})

export class AdminModule {

}

Doing what @imVinayPandya did did not work for me. I'm still getting the No component factory found for <component>. error. Putting declaration and entryComponent definitions into the base AppModule lets it work. So it does seem to be an issue with this project and lazy loaded modules. Declaring components in lazy loaded modules works in https://github.com/ng-bootstrap/ng-bootstrap

Looks like it will be fixed in next release #2556

In case @lozthiensu instructions aren't 100% for people new to ng2+ and Material 2....

Keep in mind, if you are following the material demo code (as is @lozthiensu ) then your dialogs (JazzDialog, etc.) are individual child components, which means that you'll need to also add them to your @ngModule.declarations along with the parent component that your child components are residing in. After that, you'll simply need to add your dialog child component(s) (i.e. JazzDialog) to @ngModule.entryComponents.

If you aren't familiar with entryComponents and how they differ from regular components I highly recommend spending 2 minutes reading this => https://angular.io/docs/ts/latest/cookbook/ngmodule-faq.html#!#q-entry-component-defined

Props to @lozthiensu for sharing his repo and the @angular team for having legit examples in their repo and thorough docs online. I was struggling with this one for a minute.

In my case, I was not only missing

entryComponents: [
    MyDialogComponent,
  ],

(see @msegers answer)

but also

import { MaterialModule } from '@angular/material';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
...
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    MaterialModule,
   ...
  ],

inside app.module.ts

Thank you @zurfyx, I had the same problem and I solved it adding the entryComponents tag in the main module.

Hi, @zurfyx , i'm using the "@angular/material": "^2.0.0-beta.12" and i'm facing the same issue, however MaterialModule is nolonger exported by @angular/material, How can i use your fix for the current @angular/material

I'm having the same issue with Angular 5.2.0, with the following setup:

// shared.modules.ts
@NgModule({
    declarations: [
        ModalWrapperComponent,
        GenericModalComponent,
        MessageModalComponent,
        ValidationModalComponent,
    ],
    entryComponents: [
        ModalWrapperComponent,
        GenericModalComponent,
        MessageModalComponent,
        ValidationModalComponent,
    ],
})

This module is then imported into app.module.ts. The weird thing is that ModalWrapperComponent and GenericModalComponent work fine, but MessageModalComponent and ValidationComponent throw the error, and all 4 components are loading by the exact same piece of code:

const contentFactory: ComponentFactory<{}> = this.cfr.resolveComponentFactory(this.config.component);

I debugged it, and the issue is that within CodegenComponentFactoryResolver.resolveComponentFactory, that this line:

var /** @type {?} */ factory = this._factories.get(component);

factory is undefined. Even though, when I look at it in the developer tools, all 4 components are in the list of [[Entries]] in the _factories object.

I would really suggest posting this on stackoverflow as this issue is over a year old this is probably an issue with your setup.

@adamk33n3r as you can see in my code that i have declared with AdminModule and which is lazy loaded module, still it was working fine for me.

and let me tell you one more thing, i was using Covalent theme for angular 2.

@wizlif , did you find the solution? I'm having the same issue.. adding it to entryComponents and declarations does not work for me.

SOLVED with lazy loaded module:
add dialogComponent in lazy loaded module like this
bootstrap:[dialogComponent]
but also in
declarations: [dialogComponent]

In my case, the problem was that I forgot to add MatDialogModule into the lazy loaded module:
import { MatDialogModule } from '@angular/material/dialog';
imports: [MatDialogModule]

Ok - I was having issues after following this whole thread. Posting here to help others.

Make sure you only import it in your lazy loaded module, and also add it to entryComponents - worth searching for MyDialogComponent to check it's not in any other modules.

For me i opted to just add the dialog into the component that would use it.
Within the components .html i created the dialog.

<!-- Enter Results Dialog-->
<ng-template #feedBackResults let-dialogRef="dialogRef">
  <div layout="column" layout-fill>
    <mat-form-field mat-dialog-content flex>
      <textarea matInput placeholder="Message" rows="10"></textarea>
    </mat-form-field>
    <mat-dialog-actions align="end">
      <button mat-raised-button color="warn" class="text-upper" (click)="dialogRef.close()">Close</button>
      <button mat-raised-button class="text-upper bgc-green-500 tc-white-4" (click)="sendFeedBack()">Send</button>
    </mat-dialog-actions>
  </div>
</ng-template>

And in the .ts i opened it by referencing using the id

export class ComponentName {
  @ViewChild('feedBackResults') template: TemplateRef<any>;
   private _dialogRef: MatDialogRef<any>;

   constructor(public _dialog: MatDialog){}

  openFeedbackDialog(): void {
    this._dialogRef = this._dialog.open(this.template, {
      width: '50%',
      height: '50%'
    });
  }
}
}

Then call the openFeedbackDialog() function anywhere within the component to use it.
However this will only work for a non-reusable dialog (Only available within that component.

What worked for me, was specifying the dialog component in declarations, as well as entryComponents

import { MainComponent, DialogComponent } from './my-component';
@NgModule({
  declarations: [
    DialogComponent,
    MainComponent
  ],
  entryComponents: [
        DialogComponent
    ],
})

I have the same problem but resolved now. After I generated a new component using "ng generate ..." command, and then try dialog.open it, angular throw an error about 'No component factory found for ...'. However, once I appended a route for the component, it works fine.

@scozma You're a lifesaver, that was my issue. As well. I had my component with dialog in a lazy loaded module, in declarations and entryComponents, and the actual issue was not importing matDialog. For the record, it was also necessary to put it in declarations and entryComponents, it just wasn't enough.

In my case, I imported MatDialogModule into my lazy loaded module, but still used MatDialog instance from root module, because MatDialog was injected into my own DialogService, which is provided in root module. When I use correct MatDialog instance, from lazy loaded module, there is no error.

@MartinQJD you saved me from a severe headache after one hour of trying to figure out what I was missing. Thank you very much for the discovery

Still having this problem. I don't even have lazy loading in my app, just a single app.module. Tried everything listed here but still getting the No Component Factory message. Here's my app.module:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { MainComponent } from './main/main.component';
import { DragDropModule } from '@angular/cdk/drag-drop';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ScrollingModule } from '@angular/cdk/scrolling';
import { MatCheckboxModule, MatInputModule, MatDialogModule } from '@angular/material';

import { HttpClientModule } from '@angular/common/http';
import { BoardComponent } from './board/board.component';
import { DialogComponent } from './dialog/dialog.component';

@NgModule({
  declarations: [
    AppComponent,
    MainComponent,
    BoardComponent,
    DialogComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    DragDropModule,
    BrowserAnimationsModule,
    ScrollingModule,
    MatCheckboxModule,
    MatInputModule,
    HttpClientModule,
    MatDialogModule
  ],
  entryComponents: [
    DialogComponent
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

@mamatela - Can you please create a plunker or something similar, so we can have a look?

@mamatela - I did everything suggested here and it still didn't work. In the end simply changing the path of the import did the trick:

This works:
import { DialogBodyComponent } from '../../Components/dialog-body/dialog-body.component';

This doesn't:
import { DialogBodyComponent } from '../dialog-body/dialog-body.component';

So going back up another folder makes a difference for me. Not sure why, but that's what I'm seeing. Maybe will help someone else figure it out. Took me a long time to find this.

@jobbo69 - Thanks for sharing that, didn't work for me though.
I've been trying things around and the dialog seems to be working fine when I call it from all other components, except this one component which I dynamically generate with *ngFor.
I created a new test component which I also dynamically generate using *ngFor from the same component as the culprit above, and it worked from there too. Seems *ngFor is not the issue. I will dig deeper and make a post when I find a solution.
@scozma - I need to figure out Plunkr first :D

I found the goddamn problem. I had a syntax error when importing the dialog component.

The Problem (".js"):
import { DialogComponent } from '../dialog/dialog.component.js';

Solution:
import { DialogComponent } from '../dialog/dialog.component';

I'm not even gonna say how much time I spent on this:P

Glad you found it! I've noticed even capitalization matters in that string.

Bootstrapping the component works for me :)

@mamatela Legend! I spent 2 days trying to fix this issue

@mamatela Not all heroes wear capes! You are a true savior!

I know this is specifically an issue discussing Material, but for anyone using the Overlay CDK separately, I had to Add OverlayModule as an import in my Lazy Loaded Sub Module.

@NgModule({
  imports: [
    ...,
    OverlayModule
  ],
  providers: [
    ...,
    CustomDialogService
  ],
  declarations: [
    ...,
    DialogBodyComponent
  ],
  entryComponents: [
    ...,
    DialogBodyComponent
  ],
})
export class SubModule {}

Here you can find more information about entryComponents: https://material.angular.io/components/dialog/overview#configuring-dialog-content-via-code-entrycomponents-code-

There seems to be a bug with angular where entryComponents of lazy loaded modules cannot be accessed by services outside of that module. When the service tries to use the ComponentFactoryResolver the factory will be undefined and throw the error. That's why when adding it to the app.module's entryComponents it works flawlessly.

https://github.com/angular/angular/issues/14324

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings