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


#1

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?


#2

Have you try to add quote around the modal name?

component: 'ModalPage',

instead of

component: ModalPage,

#3

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)


#4

[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


#5

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.


#6

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


#7

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


#8

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.


#9

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


#11

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();
}


#12

#13

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.


#14

it’s also displayed in the post I linked


#15

Yes this is the way to do it


#16

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


#17

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

#19

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.


#20

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


#21

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