[SOLVED] [Ionic 4] Need to know how to work the Modal Controller

Hello fellow Ionic developers,

The following is the new way of launching a modal, from my understanding, can be done with async/await or just with .then. Taken from beta.ionicframework.com website, this is the modal-example.ts:

import { Component } from '@angular/core';
import { ModalController } from '@ionic/angular';
import { ModalPage } from '../modal/modal.page';
@Component({
  selector: 'modal-example',
  templateUrl: 'modal-example.html',
  styleUrls: ['./modal-example.css']
})
export class ModalExample {
  constructor(public modalController: ModalController) {}

  async presentModal() {
    const modal = await this.modalController.create({
      component: ModalPage,
      componentProps: { value: 123 }
    });
    return await modal.present();
  }
}

Of course in modal-example.html

<ion-button (click)="presentModal()">Launch Modal</ion-button>

Question:
How to load the page on the modal? When the button is pressed I keep getting error, Component factory was not found.
I tried loading the page normally (declaring at app.module.ts and modal-example.ts) and via lazy load but was not able to launch a modal. I understand that to launch a Modal Controller in Ionic 3, you can do it with lazy load, any ideas?

6 Likes

Have you try to add quote around the modal name?

component: 'ModalPage',

instead of

component: ModalPage,
2 Likes

I’ve found the solution to this.

Just add the PageModule of your page to the imports in app.module.ts or components.module.ts (your choice)

10 Likes

[SOLVED] Yeap, MattE you are correct, import into app.module.ts first the PageModule and then only you can import into Home

So, for future references, here’s my code:

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule, RouteReuseStrategy } from '@angular/router';

import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import {FirstPageModule} from './first/first.module'





@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule,FirstPageModule],
  providers: [
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

home.ts

import { Component } from '@angular/core';
import { NavController,AlertController,ModalController } from '@ionic/angular';
import {FirstPage} from '../first/first.page';


@Component({
  selector: 'app-page-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss']
})
export class HomePage {
  constructor( private modalCtrl:ModalController,private alertCtrl:AlertController) {}

  async moveToFirst()
  {
    const modal = await this.modalCtrl.create({
     component: FirstPage
   });

   return await modal.present();
  }
}

This will open my modal. Closing it is a whole other thing, instead of getting ViewController to do it, you need to get ModalController to do it with this.modalCtrl.dismiss. Here’s how I closed the modal from first.page.ts

import { Component, OnInit } from '@angular/core';
import { NavController,ModalController } from '@ionic/angular';


@Component({
  selector: 'first',
  templateUrl: './first.page.html',
  styleUrls: ['./first.page.scss'],
})
export class FirstPage implements OnInit {



  constructor(private nav:NavController,private modalCtrl:ModalController) { }

  ngOnInit() {

  }

  closeModal()
  {
    this.modalCtrl.dismiss();
  }

Hope that helps someone in the future to do modal

26 Likes

I did something slightly different.
On the page module that requires the modal I added the modal page to the declarations, and both calling page and modal page to the entryComponents array. That works quite well.
Also tried using a shared module but that didn’t work for me.

Just another approach for doing the same. Best regards.

1 Like

Well, both of those work, but is it possible to lazy load the modal page… I have a couple of modals that are used in many places (one is a login modal, and the other is a Help Modal), but the user typically won’t use them at all, so I prefer not to load the page inside the modal unless it’s actually used.

That was easy to do with Ionic 3, but I haven’t come up with a way to do it in Ionic 4

I have not figured out how to lazy load too. If someone is able to figure out lazy load, then that would be great

Hi razmans,

I am having same issue and tried your solution but still same error, "ERROR Error: Uncaught (in promise): Error: No component factory found for GetAddressesPage. Did you add it to @NgModule.entryComponents?"

Here is my code.
app.module.ts

import {GetAddressesPageModule} from ‘./pages/get-addresses/get-addresses.module’;

imports: [
BrowserModule,
HttpClientModule,
RouterModule,
FormsModule,
GetAddressesPageModule,
ReactiveFormsModule,
IonicModule.forRoot(),
AppRoutingModule
],

In the broadband- availability , I have to open the modal
import { GetAddressesPage } from ‘…/get-addresses/get-addresses.page’;
async presentAddressModal() {
const modal = await this.modalCtrl.create({
component: ‘GetAddressesPage’,
componentProps: { postcode: this.postcode.value}
});

return await modal.present();

}

Could you please what’s wrong? I am really fedup with this upgrade to ionic 4 beta.

Sorry it’s working now. i need to remove quote from the component.

Hi razmans,

While closing the popup if i want to pass the data and handle the event, how can i do it?

Earlier version i was doing like this.

presentAddressModal() {
let addressModal = this.modalCtrl.create(GetAddressesPage, { postcode: this.postcode.value });
addressModal.onDidDismiss(data => {
if(data.action == ‘Select’)
{
this.AddressRefNum = data.AddressRefNum;
this.DistrictCode = data.DistrictCode;
this.onSubmit();
}
});
addressModal.present();
}

Hi reedrichards,

That is for to pass the data to the modal page, i am talking about to handle operations after closing the modal and back to the ordiginal page, there i want to perform few more operations after closing the modal.

like this in modal page,

let data = { ‘action’:‘Select’,‘AddressRefNum’: AddressRefNum, ‘DistrictCode’: DistrictCode};
this.modalCtrl.dismiss(data);

where i passed these data and i want to handle next operation using these data.

Hope this helps.

it’s also displayed in the post I linked

Yes this is the way to do it

@ razmans thanks! including it in app.module.ts fixed it for me. it wasn’t documented in any of the Ionic docs.

just change this way and it works perfectly.

FirstPageModule in declarations and entryComponents not in imports

@NgModule({
  declarations: [AppComponent, FirstPageModule],
  entryComponents: [FirstPageModule],
  imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule],
2 Likes

the @luisgls18 answer work very well and let you use lazyload, you can use entryComponents and declarations in the module declaration page that you want to load the popup.

Hi,
I have my code like your, but when I do present(), aparantly the modal is load because I can see in console the result of the modal when load
ngOnInit() {
console.log(this.value);
}

but do not show anything.

What Im doing wrong?

help please

if you put that in declaration and EntryComponents like you said

@NgModule({
declarations: [AppComponent, FirstPageModule],
entryComponents: [FirstPageModule],
imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule],

it send an error, unless instead of this
import {FirstPageModule} from ‘./first/first.module’
put this
import {FirstPage } from ‘./first/first.page’
and

@NgModule({
declarations: [AppComponent, FirstPage],
entryComponents: [FirstPage],
imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule],

I have done everything indicated and I continue to see the following error

Any suggestions?