Skip to content

Dialog demo - error No component factory found for #1491

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
hafquangbaox opened this issue Oct 13, 2016 · 46 comments
Closed

Dialog demo - error No component factory found for #1491

hafquangbaox opened this issue Oct 13, 2016 · 46 comments

Comments

@hafquangbaox
Copy link

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

@msegers
Copy link

msegers commented Oct 13, 2016

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

@emilio-martinez
Copy link
Contributor

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.

@dfarago
Copy link

dfarago commented Oct 13, 2016

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

@dfarago
Copy link

dfarago commented Oct 13, 2016

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

@hafquangbaox
Copy link
Author

hafquangbaox commented Oct 13, 2016

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.

@dfarago
Copy link

dfarago commented Oct 13, 2016

That seemed to work! Thanks!

@hafquangbaox
Copy link
Author

OK, close it

@PostImpatica
Copy link

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

@xtianus79
Copy link

@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.

@mark-langer
Copy link

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.

@xtianus79
Copy link

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

@chrissena
Copy link

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

@arlowhite
Copy link

arlowhite commented Jan 30, 2017

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?

@imVinayPandya
Copy link

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 {

}

@adamk33n3r
Copy link

adamk33n3r commented Feb 7, 2017

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

@adamk33n3r
Copy link

Looks like it will be fixed in next release #2556

@offroadkev
Copy link

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.

@zurfyx
Copy link

zurfyx commented Jun 1, 2017

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

@jhoncamargo
Copy link

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

@wizlif
Copy link

wizlif commented Dec 1, 2017

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

@kadamgreene
Copy link

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.

@msegers
Copy link

msegers commented Jan 16, 2018

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

@imVinayPandya
Copy link

@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.

@rottenoats
Copy link

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

@ejvargasp
Copy link

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

@scozma
Copy link

scozma commented Mar 14, 2018

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]

@bluelightning2k
Copy link

bluelightning2k commented Mar 15, 2018

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.

@wizlif
Copy link

wizlif commented Mar 21, 2018

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.

@jschuler
Copy link

jschuler commented Apr 4, 2018

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
    ],
})

@MartinQJD
Copy link

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.

@tinyweasel
Copy link

tinyweasel commented May 30, 2018

@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.

@icesmith
Copy link

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.

@greedman456
Copy link

@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

@mamatela
Copy link

mamatela commented Jan 15, 2019

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

@scozma
Copy link

scozma commented Jan 15, 2019

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

@jobbo69
Copy link

jobbo69 commented Jan 16, 2019

@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.

@mamatela
Copy link

mamatela commented Jan 17, 2019

@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

@mamatela
Copy link

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

@jobbo69
Copy link

jobbo69 commented Jan 18, 2019

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

@localdevm
Copy link

Bootstrapping the component works for me :)

@cediim8
Copy link

cediim8 commented Mar 8, 2019

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

@scharnyw
Copy link

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

@ChazUK
Copy link

ChazUK commented Mar 18, 2019

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

@m5x5
Copy link

m5x5 commented Jul 19, 2019

@Buttars
Copy link

Buttars commented Aug 27, 2019

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.

angular/angular#14324

@angular-automatic-lock-bot
Copy link

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 27, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests