Change on modal pages

Suddenlly, my project started to complain about modal pages being declared in two places. I declare all modal pages on the app.module.ts, on both declarations and entryComponents (as I learned from several online examples) and the app was working ok and I was able to build APKs without problems.

A couple of days ago I tried to build the APK again and got this:
ERROR in : Type ReparacionPage in reparacion.page.ts is part of the declarations of 2 modules: AppModule in app.module.ts and ReparacionPageModule in reparacion.module.ts! Please consider moving ReparacionPage in reparacion.page.ts to a higher module that imports AppModule in app.module.ts and ReparacionPageModule in reparacion.module.ts. You can also create a new NgModule that exports and includes ReparacionPage in reparacion.page.ts then import that NgModule in AppModule in app.module.ts and ReparacionPageModule in reparacion.module.ts.

I took me a while to understand what was happening and then moving the modal declarations to the appropriate place. My point is that these changes that are not backward compatible, creates confusion and problems. One of the things I hate the most about .NET is that you NEVER NOW if your products will work on the next version of the Framework.

Hoping this is not also the case with Ionic :frowning:

I’m confused about how anything in Ionic tooling could be having this sort of effect on an existing code base. I could see how if you were using page generators and weren’t accustomed to the sort of boilerplate they make, and you had added some new pages recently, this might happen. One thing you could do is simply not use the page generators at all and just organize your code the way you prefer. Angular’s pretty tolerant of all sorts of layout strategies.

Well, maybe is because I am newbie to Ionice. In fact, the problem with modal pages is still present, I just discovered. If I declare the modal page in declarations/entryComponents at app,module.ts, I get the error I mentioned. I moved to the parent page (the one that actually calls the modal) and the compiler error dissapeared…but now it pops out again when I try to call the modal, so, at this moment, I don’t know how to properly call a modal page with lazy loading :frowning:

modal page declaration (muestra.module.ts):

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Routes, RouterModule } from '@angular/router';
import { IonicModule } from '@ionic/angular';
import { MuestraPage } from './muestra.page';

const routes: Routes = [
  {
    path: '',
    component: MuestraPage
  }
];

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    IonicModule,
    RouterModule.forChild(routes)
  ],
  declarations: [MuestraPage],
  entryComponents: [MuestraPage]
})
export class MuestraPageModule {}

parent page declaration (muestras.module.ts):

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Routes, RouterModule } from '@angular/router';
import { IonicModule } from '@ionic/angular';
import { MuestrasPage } from './muestras.page';
import { ComponentsModule } from '../../components/components.module';

const routes: Routes = [
  {
    path: '',
    component: MuestrasPage
  }
];

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    IonicModule,
    ComponentsModule,
    RouterModule.forChild(routes)
  ],
  declarations: [
    MuestrasPage
  ],
  entryComponents: [
  ],
  schemas: [
  ]
})
export class MuestrasPageModule {}

caller method:

async nuevaMuestra() {
    const modal = await this.modalController.create({
      component: MuestraPage,
      componentProps: {
        tipo: this.currentTab.toUpperCase(),
        statusTunel: this.tunel.status,
        muestras: this.muestras.filter(x => x.tipo == this.currentTab.toUpperCase())
      },
      backdropDismiss: false
    });
    modal.onDidDismiss()
         .then(res => {
            if (res.data)
              this.agregarMuestra(res.data);
         });
    return await modal.present();
  } // nuevaMuestra

The error I have right now:
ERROR Error: Uncaught (in promise): Error: No component factory found for MuestraPage. Did you add it to @NgModule.entryComponents?

When I declare MuestraPage in MuestrasPage module, then I get this when try to load the modal:

ERROR Error: Uncaught (in promise): Error: Type MuestraPage is part of the declarations
 of 2 modules: MuestraPageModule and MuestrasPageModule! Please consider moving
MuestraPage to a higher module that imports MuestraPageModule and
 MuestrasPageModule. You can also create a new NgModule that exports and includes 
MuestraPage then import that NgModule in MuestraPageModule and 
MuestrasPageModule.

You said you wanted to do lazy loading, so I would suggest exporting MuestraPage out of MuestraPageModule and then importing MuestraPageModule into MuestrasPageModule.

I still can’t make modals to work. I thought I had fixed it because it was working on browser, but now I compiled to Android and the problem is back :frowning:

This my modal page’s module (muestra.module.ts):

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Routes, RouterModule } from '@angular/router';
import { IonicModule } from '@ionic/angular';
import { MuestraPage } from './muestra.page';

const routes: Routes = [
  {
    path: '',
    component: MuestraPage
  }
];

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    IonicModule,
    RouterModule.forChild(routes)
  ],
  declarations: [MuestraPage],
  entryComponents: [MuestraPage]
})
export class MuestraPageModule {}

This is the parent page’s module, where the modal is invoked (muestras.module.ts):

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Routes, RouterModule } from '@angular/router';
import { IonicModule } from '@ionic/angular';
import { MuestrasPage } from './muestras.page';
import { MuestraPage } from '../../modals/muestra/muestra.page';
import { FotosPage } from '../../modals/fotos/fotos.page';
import { ComponentsModule } from '../../components/components.module';

const routes: Routes = [
  {
    path: '',
    component: MuestrasPage
  }
];

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    IonicModule,
    ComponentsModule,
    RouterModule.forChild(routes)
  ],
  declarations: [
    MuestrasPage,
    MuestraPage,
    FotosPage
  ],
  entryComponents: [
    MuestraPage,
    FotosPage
  ],
  schemas: [
  ]
})
export class MuestrasPageModule {}

This is how I invoke the modal:

 async nuevaMuestra() {
    const tipo = this.currentTab;
    const modal = await this.modalController.create({
      component: MuestraPage,
      componentProps: {
        tipo: this.currentTab,
        statusTunel: this.tunel.status,
        muestras: this.muestras.filter(x => x.mtu_tipo == tipo)
      },
      backdropDismiss: false
    });
    modal.onDidDismiss()
         .then(res => {
            if (res.data)
              this.agregarMuestra(res.data);
         });
    return await modal.present();
  } // nuevaMuestra

And this is what I get when trying to navigate to the modal’s parent page (muestras):

This code works in the browser… most of the time… some times it raises the same error, but then I reload the page a couple of times and then everything works ok for a while.

What I am doing wrong?? What do I have to do to have a simple modal form working on both platforms???

TIA

It’s not a modal issue but components and angular modules

You cannot declare one component to be part of two modules. So u need to move it out one module. There is sufficient stuff on the internet on this (can’t help from my phone)

My experience with modals is, btw, that I need to change the route of the modal into something random/different as apparently the modal route conflicts with the caller

Thanks a lot!! I finally understood what you meant about “declaring the page in two modules” and now is finally work on browser AND device!! Just changed the module declaration in the modal’s module file to this:

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    IonicModule,
    RouterModule.forChild(routes)
  ],
  declarations: [],    <-- Remove MuestraPage from here
  entryComponents: []   <-- and from here
})

I also understand now what you meant about using the CLI boilerplate was causing the problem. Nevertheless, I found the boilerplates pretty useful, so all I have to do is to remember to clear declarations and entryComponents in the modal’s module and I will be go to go.

1 Like

Love it when a plans comes together

Welcome to the next level!

Ps. De boilerplate comment came from @rapropos who basically said the same thing in his other post. Sometimes an extra hint is needed to push the learning experience

Indeed. I am really loving working with this framework. I hope I can achieve the enough expertise to begin collaborating as well with the base code at some point.

1 Like