Search code examples
angularangular-materialangular-material2

Can't implement Angular Material Popup Dialog as separate component in Angular 4


I'm trying to implement a popup with Angular 4 with an Angular cli build - all latest versions.

I have followed the code from this Plunker so far almost exactly: https://plnkr.co/edit/Dh9INs7QZPatSyhHywJc?p=preview

But I want to use a separate component for the actual popup dialog so I can style it better and so it fits into the modular architecture of a rapidly expanding web-app.

My app.module code:

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

import { routes } from './app.router';

import 'hammerjs';

import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule } from '@angular/forms';
import { MdInputModule, MdButtonModule, MdToolbarModule, MdMenuModule, MdGridListModule, MdDialogModule } from '@angular/material';


import { CommissionMeComponent } from './commission-me/commission-me.component';
import { CommissionMeDialogComponent } from './commission-me-dialog/commission-me-dialog.component';


@NgModule({
  declarations: [
    CommissionMeComponent,
    CommissionMeDialogComponent
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    FormsModule,
    MdInputModule,
    MdButtonModule,
    MdToolbarModule,
    MdMenuModule,
    MdDialogModule,
    routes
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

My Component html for the component with the button that calls the dialog:

<button (click)="openDialog()">Launch dialog</button>

My Component ts for the component with the button that calls the dialog:

import { Component } from '@angular/core';
import {MdDialog, MdDialogRef} from '@angular/material';

import { CommissionMeDialogComponent } from '../commission-me-dialog/commission-me-dialog.component';

@Component({
  selector: 'app-commission-me',
  templateUrl: './commission-me.component.html',
  styleUrls: ['./commission-me.component.css']
})

export class CommissionMeComponent {

  selectedOption: string;

  constructor(public dialog: MdDialog) {}

  openDialog() {
    let dialogRef = this.dialog.open(CommissionMeDialogComponent);
    dialogRef.afterClosed().subscribe(result => {
      this.selectedOption = result;
    });
  }
}

My Component html for the dialog component:

<h1>Dialog</h1>

My Component ts for the dialog component:

import { Component } from '@angular/core';
import { MdDialog, MdDialogRef } from '@angular/material';

@Component({
  selector: 'app-commission-me-dialog',
  templateUrl: './commission-me-dialog.component.html',
  styleUrls: ['./commission-me-dialog.component.css']
})


export class CommissionMeDialogComponent {
  constructor(public dialogRef: MdDialogRef<CommissionMeDialogComponent>) {}
}

What I see when I click the button to call the dialog is just a thin grey thing down the left side of the browser window - it's kind of a dialog but without the text.

These are the errors in the Chrome console:

CommissionMeComponent.html:3 ERROR Error: No component factory found for CommissionMeDialogComponent. Did you add it to @NgModule.entryComponents?
    at noComponentFactoryError (core.es5.js:3202)
    at CodegenComponentFactoryResolver.webpackJsonp.../../../core/@angular/core.es5.js.CodegenComponentFactoryResolver.resolveComponentFactory (core.es5.js:3267)
    at PortalHostDirective.webpackJsonp.../../../cdk/@angular/cdk.es5.js.PortalHostDirective.attachComponentPortal (cdk.es5.js:2706)
    at MdDialogContainer.webpackJsonp.../../../material/@angular/material.es5.js.MdDialogContainer.attachComponentPortal (material.es5.js:17625)
    at MdDialog.webpackJsonp.../../../material/@angular/material.es5.js.MdDialog._attachDialogContent (material.es5.js:17901)
    at MdDialog.webpackJsonp.../../../material/@angular/material.es5.js.MdDialog.open (material.es5.js:17813)
    at CommissionMeComponent.webpackJsonp.../../../../../src/app/commission-me/commission-me.component.ts.CommissionMeComponent.openDialog (commission-me.component.ts:19)
    at Object.eval [as handleEvent] (CommissionMeComponent.html:3)
    at handleEvent (core.es5.js:12004)
    at callWithDebugContext (core.es5.js:13465)
View_CommissionMeComponent_0 @ CommissionMeComponent.html:3
proxyClass @ compiler.es5.js:14971
webpackJsonp.../../../core/@angular/core.es5.js.DebugContext_.logError @ core.es5.js:13405
webpackJsonp.../../../core/@angular/core.es5.js.ErrorHandler.handleError @ core.es5.js:1080
(anonymous) @ core.es5.js:9217
(anonymous) @ platform-browser.es5.js:2651
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:424
onInvokeTask @ core.es5.js:3881
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:423
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.runTask @ zone.js:191
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneTask.invokeTask @ zone.js:498
invokeTask @ zone.js:1370
globalZoneAwareCallback @ zone.js:1388
CommissionMeComponent.html:3 ERROR CONTEXT DebugContext_ {view: {…}, nodeIndex: 2, nodeDef: {…}, elDef: {…}, elView: {…}}
View_CommissionMeComponent_0 @ CommissionMeComponent.html:3
proxyClass @ compiler.es5.js:14971
webpackJsonp.../../../core/@angular/core.es5.js.DebugContext_.logError @ core.es5.js:13405
webpackJsonp.../../../core/@angular/core.es5.js.ErrorHandler.handleError @ core.es5.js:1085
(anonymous) @ core.es5.js:9217
(anonymous) @ platform-browser.es5.js:2651
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:424
onInvokeTask @ core.es5.js:3881
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask @ zone.js:423
webpackJsonp.../../../../zone.js/dist/zone.js.Zone.runTask @ zone.js:191
webpackJsonp.../../../../zone.js/dist/zone.js.ZoneTask.invokeTask @ zone.js:498
invokeTask @ zone.js:1370
globalZoneAwareCallback @ zone.js:1388

Solution

  • You are missing entry component for the dialog. In your app module, add the following:

    declarations: [
        CommissionMeComponent,
        CommissionMeDialogComponent
      ],
      entryComponents: [CommissionMeDialogComponent]