Lazy Loading LoadingController Instance Error


#1

This was a really hard problem to search for, and the best I could find related was here:

Basically, I have a lazy loaded IonicPage. In the page is a method that pulls up a Loader. I’ve made a cut down example below.

With lazy loading I get an exception:

LazyTestPage.html:18 ERROR TypeError: Cannot read property '_getPortal' of undefined
    at App.present (app.js:241)
    at Loading.present (loading.js:88)
    at LazyTestPage.webpackJsonp.721.LazyTestPage.testLoadPopup (lazy-test.ts:48)
    at Object.eval [as handleEvent] (LazyTestPage.html:18)
    at handleEvent (core.js:13254)
    at callWithDebugContext (core.js:14739)
    at Object.debugHandleEvent [as handleEvent] (core.js:14326)
    at dispatchEvent (core.js:9703)
    at core.js:12027
    at SafeSubscriber.schedulerFn [as _next] (core.js:4232)

Here’s the lazy-test.module.ts:

import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { LazyTestPage } from './lazy-test';
import {ComponentsModule} from "../../../components/components.module";

@NgModule({
  declarations: [
    LazyTestPage,
  ],
  imports: [
    ComponentsModule,
    IonicPageModule.forChild(LazyTestPage),
  ],
})
export class LazyTestPageModule {}

And here’s the IonicPage:

lazy-test.ts

import {Component} from '@angular/core';
import {IonicPage, LoadingController, NavController, NavParams} from 'ionic-angular';

@IonicPage()
@Component({
  selector: 'page-lazy-test',
  templateUrl: 'lazy-test-page.html',
})
export class LazyTestPage {

  constructor(public navCtrl: NavController, public navParams: NavParams, public loadingCtrl: LoadingController) {}

  ionViewDidLoad() {
    console.log('ionViewDidLoad LazyTestPage');
  }

  testLoadPopup() {

    let loader = this.loadingCtrl.create({
      content: "Loading. Please wait..."
    });
    loader.present();
  }

And for completeness the template lazy-test-page.html:

<ion-content padding>
     <a href='#' (click)="testLoadPopup()">Test</a>
</ion-content>

Can anyone help me identify what I’m doing wrong? In the other thread I saw the suggestion to replace IonicModule.forChild(LazyTestPage) with simply IonicModule, however that opens a completely different can of worms. It seems to be related to some injection in nav controller that even prevents the parent page from navigating to LazyTestPage? So doing the swap and then clicking the [navPush]='LazyTestPage' from the parent gives me:

ERROR Error: Uncaught (in promise): Error: StaticInjectorError[InjectionToken LZYCMP]: 
  StaticInjectorError[InjectionToken LZYCMP]: 
    NullInjectorError: No provider for InjectionToken LZYCMP!
Error: StaticInjectorError[InjectionToken LZYCMP]: 
  StaticInjectorError[InjectionToken LZYCMP]: 
    NullInjectorError: No provider for InjectionToken LZYCMP!
    at _NullInjector.get (core.js:923)
    at resolveToken (core.js:1211)
    at tryResolveToken (core.js:1153)
    at StaticInjector.get (core.js:1024)
    at resolveToken (core.js:1211)
    at tryResolveToken (core.js:1153)
    at StaticInjector.get (core.js:1024)
    at resolveNgModuleDep (core.js:10584)
    at NgModuleRef_.get (core.js:11805)
    at resolveNgModuleDep (core.js:10584)
    at _NullInjector.get (core.js:923)
    at resolveToken (core.js:1211)
    at tryResolveToken (core.js:1153)
    at StaticInjector.get (core.js:1024)
    at resolveToken (core.js:1211)
    at tryResolveToken (core.js:1153)
    at StaticInjector.get (core.js:1024)
    at resolveNgModuleDep (core.js:10584)
    at NgModuleRef_.get (core.js:11805)
    at resolveNgModuleDep (core.js:10584)
    at c (polyfills.js:3)
    at Object.reject (polyfills.js:3)
    at NavControllerBase._fireError (nav-controller-base.js:223)
    at NavControllerBase._failed (nav-controller-base.js:216)
    at nav-controller-base.js:263
    at t.invoke (polyfills.js:3)
    at Object.onInvoke (core.js:4626)
    at t.invoke (polyfills.js:3)
    at r.run (polyfills.js:3)
    at polyfills.js:3

Incidentally, this error also seems to persist when a form ionic popup also tries to be loaded (e.g. ionic-select)

My suspicion is that these components aren’t wrapped in pages like Modals which are ok with the lazy loading. Other than that I’m not sure how to approach this.


#2

As far as I can tell your code looks fine.

What does ionic info output?


#3

Why do you have an href instead of an ion-button? Also, in your real page, are you doing things before ionViewWillEnter, or before ngAfterViewInit? If so, you might need to slow down a bit.


#4

Here’s ionic info:

ionic info

cli packages: (/Users/matt/.npm-global/lib/node_modules)

    @ionic/cli-utils  : 1.19.0
    ionic (Ionic CLI) : 3.19.0

global packages:

    cordova (Cordova CLI) : 7.1.0

local packages:

    @ionic/app-scripts : 3.1.5
    Cordova Platforms  : none
    Ionic Framework    : ionic-angular 3.9.2

System:

    Android SDK Tools : 26.1.1
    Node              : v8.7.0
    npm               : 5.4.2
    OS                : macOS Sierra
    Xcode             : Xcode 9.2 Build version 9C40b

Environment Variables:

    ANDROID_HOME : /usr/local/share/android-sdk

Misc:

    backend : pro

#5

Hello @mattio,

To me you should start at the root of the problem:

  1. LazyTestPage.html:18 ERROR TypeError: Cannot read property ‘_getPortal’ of undefined

Your call to any database seems to return a null result, that is on your side

  1. Not sure what kind of Linux server you use, but there is obviously an issue in the urls in server.conf (debian.conf style or apache / nginx style webserver configuration files).

Hope that helps,

François


#6

(apparently I’m being rate limited by ionic forum. tried to reply earlier but wasn’t allowed :disappointed: Then I went on holiday before realizing I never replied! )

You’re right it’s an ion button. I don’t know why I changed it to an href for my contrived example, heh.

There’s nothing in either ionViewWillEnter or ngAfterViewInit. Could that be the issue? I need to make sure LoadingController is there? I thought providing it to the constructor would be enough?