ionic-team / ionic-framework

A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.
https://ionicframework.com
MIT License
51.03k stars 13.51k forks source link

Ionic v2 - Loading Service - Throwing error "cannot read property 'nativeElement' ..." #6209

Closed tonyawad88 closed 7 years ago

tonyawad88 commented 8 years ago

Short description of the problem:

I have a welcome page that invokes the Loading service in its constructor. As soon as the page loads for the first time the error / exception is thrown.

What behavior are you expecting?

No exceptions thrown.

Steps to reproduce:

  1. Create a new ionic project ionic start MyIonic2Project tutorial --v2 --ts
  2. On the root page, add in its constructor the following:
import {Page,Loading,NavController} from 'ionic-angular';
@Page({
  templateUrl: 'build/pages/hello-ionic/hello-ionic.html'
})
export class HelloIonicPage {
  constructor(private nav: NavController) {
    this.nav =nav;
    let loading = Loading.create({
      content: "Please wait...",
      duration: 3000,
      dismissOnPageChange: true
    });
    this.nav.present(loading);
  }
}

3 . Check the console for the exception

Other information: (e.g. stacktraces, related issues, suggestions how to fix, stackoverflow links, forum links, etc)

browser_adapter.ts:73 STACKTRACE:BrowserDomAdapter.logError @ browser_adapter.ts:73ExceptionHandler.call @ exception_handler.ts:52(anonymous function) @ application_ref.ts:258schedulerFn @ async.ts:127SafeSubscriber.__tryOrUnsub @ Subscriber.js:166SafeSubscriber.next @ Subscriber.js:115Subscriber._next @ Subscriber.js:74Subscriber.next @ Subscriber.js:51Subject._finalNext @ Subject.js:124Subject._next @ Subject.js:116Subject.next @ Subject.js:73EventEmitter.emit @ async.ts:113NgZone._zoneImpl.ng_zone_impl_1.NgZoneImpl.onError @ ng_zone.ts:134NgZoneImpl.inner.inner.fork.onHandleError @ ng_zone_impl.ts:88ZoneDelegate.handleError @ angular2-polyfills.js:336Zone.runGuarded @ angular2-polyfills.js:244NgZoneImpl.runInner @ ng_zone_impl.ts:97NgZone.run @ ng_zone.ts:204NavController._afterTrans @ nav-controller.js:1003(anonymous function) @ nav-controller.js:979Animation._didFinish @ animation.js:590Animation.play @ animation.js:264(anonymous function) @ nav-controller.js:990ZoneDelegate.invoke @ angular2-polyfills.js:332Zone.run @ angular2-polyfills.js:227NgZoneImpl.runOuter @ ng_zone_impl.ts:98NgZone.runOutsideAngular @ ng_zone.ts:218NavController._beforeTrans @ nav-controller.js:948NavController._postRender @ nav-controller.js:930(anonymous function) @ nav-controller.js:865(anonymous function) @ nav-controller.js:1217promiseReactionJob @ es6-shim.js:2171(anonymous function) @ es6-shim.js:2159Item.run @ browser.js:64drainQueue @ browser.js:34ZoneDelegate.invokeTask @ angular2-polyfills.js:365NgZoneImpl.inner.inner.fork.onInvokeTask @ ng_zone_impl.ts:54ZoneDelegate.invokeTask @ angular2-polyfills.js:364Zone.runTask @ angular2-polyfills.js:263ZoneTask.invoke @ angular2-polyfills.js:431
browser_adapter.ts:73 TypeError: Cannot read property 'nativeElement' of undefined
    at new LoadingMdPopOut (http://localhost:8101/build/js/app.bundle.js:44356:40)
    at Function.Transition.createTransition (http://localhost:8101/build/js/app.bundle.js:63476:16)
    at http://localhost:8101/build/js/app.bundle.js:46769:58
    at ZoneDelegate.invoke (http://localhost:8101/build/js/angular2-polyfills.js:332:29)
    at Zone.run (http://localhost:8101/build/js/angular2-polyfills.js:227:44)
    at NgZoneImpl.runOuter (http://localhost:8101/build/js/app.bundle.js:26898:71)
    at NgZone.runOutsideAngular (http://localhost:8101/build/js/app.bundle.js:26817:80)
    at Portal.NavController._beforeTrans (http://localhost:8101/build/js/app.bundle.js:46759:20)
    at Portal.NavController._postRender (http://localhost:8101/build/js/app.bundle.js:46741:14)
    at Portal.NavController._render (http://localhost:8101/build/js/app.bundle.js:46657:18)
  -------------   Elapsed: 77 ms; At: Sun Apr 17 2016 13:54:49 GMT-0400 (EDT)   -------------  
    at Object.Zone.longStackTraceZoneSpec.onScheduleTask (http://localhost:8101/build/js/angular2-polyfills.js:1354:23)
    at ZoneDelegate.scheduleTask (http://localhost:8101/build/js/angular2-polyfills.js:342:50)
    at Zone.scheduleMacroTask (http://localhost:8101/build/js/angular2-polyfills.js:283:40)
    at http://localhost:8101/build/js/angular2-polyfills.js:133:26
    at setTimeout (eval at createNamedFn (http://localhost:8101/build/js/angular2-polyfills.js:973:18), <anonymous>:3:37)
    at process.nextTick (http://localhost:8101/build/js/app.bundle.js:64854:9)
    at enqueuePromiseReactionJob (http://localhost:8101/build/js/app.bundle.js:37073:7)
    at fulfillPromise (http://localhost:8101/build/js/app.bundle.js:37099:9)
  -------------   Elapsed: 52 ms; At: Sun Apr 17 2016 13:54:49 GMT-0400 (EDT)   -------------  
    at Object.Zone.longStackTraceZoneSpec.onScheduleTask (http://localhost:8101/build/js/angular2-polyfills.js:1354:23)
    at ZoneDelegate.scheduleTask (http://localhost:8101/build/js/angular2-polyfills.js:342:50)
    at Zone.scheduleEventTask (http://localhost:8101/build/js/angular2-polyfills.js:286:40)
    at zoneAwareAddEventListener (http://localhost:8101/build/js/angular2-polyfills.js:880:11)
    at XMLHttpRequest.addEventListener (eval at createNamedFn (http://localhost:8101/build/js/angular2-polyfills.js:973:18), <anonymous>:3:43)
    at XMLHttpRequest.desc.set [as onload] (http://localhost:8101/build/js/angular2-polyfills.js:776:19)
    at XHRImpl.get (http://localhost:8101/build/js/app.bundle.js:30356:20)
    at TemplateNormalizer.normalizeTemplate (http://localhost:8101/build/js/app.bundle.js:10294:30)
  -------------   Elapsed: 327 ms; At: Sun Apr 17 2016 13:54:49 GMT-0400 (EDT)   -------------  
    at Object.Zone.longStackTraceZoneSpec.onScheduleTask (http://localhost:8101/build/js/angular2-polyfills.js:1354:23)
    at ZoneDelegate.scheduleTask (http://localhost:8101/build/js/angular2-polyfills.js:342:50)
    at Zone.scheduleMacroTask (http://localhost:8101/build/js/angular2-polyfills.js:283:40)
    at http://localhost:8101/build/js/angular2-polyfills.js:133:26
    at setTimeout (eval at createNamedFn (http://localhost:8101/build/js/angular2-polyfills.js:973:18), <anonymous>:3:37)
    at process.nextTick (http://localhost:8101/build/js/app.bundle.js:64854:9)
    at enqueuePromiseReactionJob (http://localhost:8101/build/js/app.bundle.js:37073:7)
    at Promise.then (http://localhost:8101/build/js/app.bundle.js:37438:11)

Which Ionic Version? 2.x

Plunker that shows an example of your issue

http://plnkr.co/edit/fA0KB70ggJd0nptNvYpl?p=preview

Run ionic info from terminal/cmd prompt: (paste output below)

WARN: ionic.config.js has been deprecated, you can remove it.

Your system information:

Cordova CLI: 6.0.0
Gulp version:  CLI version 3.9.0
Gulp local:   Local version 3.9.1
Ionic Framework Version: 2.0.0-beta.4
Ionic CLI Version: 2.0.0-beta.25
Ionic App Lib Version: 2.0.0-beta.15
ios-deploy version: 1.8.2 
ios-sim version: 5.0.3 
OS: Mac OS X El Capitan
Node Version: v0.12.7
Xcode version: Xcode 7.3 Build version 7D175 
ataraxus commented 8 years ago

Hello @tonyawad88,

are you using this Loading service, to load resources before your app starts rendering? I guess I stumbled uppon the same requirement and opened a more general question/request. Maybe you have a look and could link these issues, if they are similar to you?

https://github.com/driftyco/ionic/issues/6148

tonyawad88 commented 8 years ago

@ataraxus Hii, I don't think they are related. I am able to create a barebone ionic 2 plunker and replicate the issue I am having with my app.

XertroV commented 8 years ago

I have the same issue, though only when including the dismissOnPageChange: true parameter. (Does not throw an error if it's set to false)

HereThereBeMonsters commented 8 years ago

I encounter the same error, it seems that it happens when I try to dismiss the loading dialog "too quickly", e.g. when I get data out a cache instead of doing a HTTP request.

jgw96 commented 8 years ago

Thanks for the info everyone! I am able to reproduce this and we are now looking further into this.

keithdmoore commented 8 years ago

Here is a workaround that I was able to get to work:

http://plnkr.co/edit/OyGY7VVNSSAjdstr54wG?p=preview

keithdmoore commented 8 years ago

I am having the same issue when trying to use the loading component at a global level. If anyone else is having trouble with that, you might consider this until this bug is resolved at least: http://www.joshmorony.com/how-to-create-a-custom-loading-component-in-ionic-2/

keithdmoore commented 8 years ago

Here is a plunker that is using loading in a global way. http://plnkr.co/edit/3TfK76XpqsnUvW3dQuG3?p=preview

I had to do some trickier things in my implementation because I am using EventEmitters to indicate when an http request is started and when it has completed. Im still having a few issues with it but if I wrap the loading.dismiss() in a setTimeout, it seems to work.

tonyawad88 commented 8 years ago

@jgw96 Hi Justin, do you have any workaround to dismiss the loading popup manually from javascript ? Calling loading.dismiss() is always throwing the 'nativeelement' error. Thanks

jgw96 commented 8 years ago

Hey all! Can you all try with this plunker? Looks like this issue is not reproducible anymore in our latest beta.7 release! http://plnkr.co/edit/IIfn2RKAMGheD8ISVr9A?p=preview I am going to close this for now, as it seems it was fixed. But if anyone can reproduce it again with beta.7 then i will reopen. Thanks for using Ionic everyone!

tonyawad88 commented 8 years ago

@jgw96 I can still reproduce in beta 7. Enable the following property on Loading, and it will throw the 'native element' exception.

dismissOnPageChange: true

Any idea how to dismiss the loading from JS ? The use case in the plunker, where we use setTimeout are not too realistic. :)

I wonder if there is any event that we can emit to dismiss the "Loading" ?

Thank you !

keithdmoore commented 8 years ago

@jgw96 Seems like a race condition or a digest type issue. When adding the dismissOnPageChange: true I was able to reproduce. My current hack to get around this is to do the below when displaying the loading component. I wouldn't classify this issue as fixed.

   setTimeout(()=>{
      this.nav.present(loading);
   });
keithdmoore commented 8 years ago

@tonyawad88 I am using EventEmitter to handle the dismissing of the loading component.

jgw96 commented 8 years ago

Hello all, you all are correct, setting dismissOnPageChange to true makes this issue still reproducible, sorry about that! @tonyawad88 as a workaround you can use the dismiss() method on the loading component. So it would just be {{name of your loader}}.dismiss(). Hope that makes sense! I will look into this more.

keithdmoore commented 8 years ago

@tonyawad88 to be more specific here is what I am doing. (currently on beta6) In a service:

  httpRequestEventEmitter: EventEmitter<string>;
  httpResponseEventEmitter: EventEmitter<string>;

  private sendHttpRequest(request: Request, event: string): Observable<any>  {
    return Observable.of(request)
      .do((req: Request) => { this.httpRequestEventEmitter.emit(event + '-request-started'); })
      .flatMap((req: Request) => { return this.http.request(req); })
      .finally(() => {
        this.httpResponseEventEmitter.emit(event + '-request-finished');
      });
  }

In app.ts:

    this.service.httpRequestEventEmitter.subscribe(
      (data: string) => { 
          this.loading = Loading.create({
             dismissOnPageChange: true
          });
          this.app.getComponent(ROOT_NAV).present(this.loading);
      }
    );
    this.service.httpResponseEventEmitter.subscribe(
      (data: string) => { 
          this.loading.dismiss();
      }
    );
jgw96 commented 8 years ago

@keithdmoore Just to let you know we deprecated app.getComponent in beta.7 in favor of the native Angular 2 ViewChild decorator https://angular.io/docs/ts/latest/api/core/ViewChild-var.html .

keithdmoore commented 8 years ago

@jgw96 Ok. Thanks. Seems like I did see a use of ViewChild in the ionic-conference app. Thanks for the heads up! I am about to upgrade right now.

jgw96 commented 8 years ago

No problem! Let me know how the beta.7 update goes for you! Here are some awesome instructions to help you with the upgrade: https://github.com/driftyco/ionic/blob/2.0/CHANGELOG.md#angular-update-to-200-rc1

tonyawad88 commented 8 years ago

@keithdmoore @jgw96 this.loading.dismiss(); also throws the error.

It sure looks like a race. For now adding a settimeout of 500ms, around creating the "loading" prevents it from firing the exception.

Check this plunker out, if you display / hide the loading using the buttons, no exceptions occurs. As soon as you use it inside "onPageDidEnter", it throws the exception. http://plnkr.co/edit/GXugmXJi2qwaYQWKscqC

Thank you !

keithdmoore commented 8 years ago

You might try using: ngAfterViewInit I had trouble with the onPageDidEnter

biesbjerg commented 8 years ago

EDIT: Scratch that, turns out I needed/could use this._navController.present(loading).then( ... ) to avoid dismissing before loading animation was done showing.

I'm getting the same error message, but in my case it happens if I do loading.dismiss() too quickly after doing this._navController.present(loading);

My request to productService.findOne() might be cached and return immediately, and that's when the exeption is thrown.

    public ngOnInit(): void {
        let loading = Loading.create({
            content: 'Loading...'
        });
        this._navController.present(loading);

        console.log('before loading', this._navParams.data.id);

        //this._productService.clearCache();
        this._productService
            .findOne(this._navParams.data.id)
            .subscribe(
                (data) => {
                    console.log('loading success');
                    console.log(data);
                    this.product = data;
                    loading.dismiss();
                },
                (error) => {
                    console.log('Error loading product', error);
                    loading.dismiss();
                }
            );
    }
tonyawad88 commented 8 years ago

@keithdmoore same issue with "ngAfterViewInit".

Kingwl commented 8 years ago

same issue

TheBrockEllis commented 8 years ago

I am having the same issue, and it looks like it is because I'm trying to present the Loading and dismiss it too quickly. This is part of my page that handles a searchbar component:

   onSearch(searchbar){
    let loader = this.presentLoading(); // <-- init and display the loader

    // set q to the value of the searchbar
    let q = this.searchQuery;

    // if the value is an empty string return and don't do an http lookup
    if (q.trim() == '') {
      console.log("Empty searchQuery");
      this.searchQuery = null;
      loader.dismiss(); // <-- attempt to dismiss the loader
      return;
    }
    ...
  }

  presentLoading(){
    let loading = Loading.create();
    this.nav.present(loading);
    return loading;
  }

I also get the "ORIGINAL EXCEPTION: TypeError: Cannot read property 'nativeElement' of undefined".

I can confirm that adding in an artificial delay using setTimeout() when trying to clear the Loading makes it function correctly.

$ ionic info
Cordova CLI: Not installed
Ionic Framework Version: 2.0.0-beta.8
Ionic CLI Version: 2.0.0-beta.30
Ionic App Lib Version: 2.0.0-beta.16
ios-deploy version: 1.8.6
ios-sim version: 5.0.8
OS: Mac OS X El Capitan
Node Version: v4.4.5
Xcode version: Xcode 7.3.1 Build version 7D1014
jgw96 commented 8 years ago

Hello all! We are currently working on a refactor of the way "overlay components" like the loading component get pushed onto the stack. This should fix this issue. We may do a nightly that includes these changes soon and i will update this issue when that happens. Thanks!

mserge commented 8 years ago

FYI May be I'm wrong but I resolved by chaining new Promises after present has successfull

 this.nav.present(loading).then(()=>{
            return dishService.load();
        }).then(data=> {
            loading.dismiss().then(()=>{console.log('Dismissed')});
}
janein commented 8 years ago

Hi,

I know this is quite an old issue, but I'm struggling with the same problems in Ionic 2 RC1. If i set dismissOnPageChange: true or do a page-push before dismissing all loading-overlays, I get the same error as @tonyawad88 in his original post. Happens when I try to leave the page:

Cannot read property 'nativeElement' of null
risleylima commented 8 years ago

I'm using events to control the behavior of Loading Control:

this.loading = this.loadingCtrl.create({
    content:"Please wait..."
});

this.events.subscribe('ajax:start',()=>{
    this.loading.present();
});

this.events.subscribe('ajax:stop',()=>{
      this.loading.dismiss();
});

and I'm getting the following error: loading-transitions.js:52 Uncaught TypeError: Cannot read property 'nativeElement' of null

this is the full stacktrace, maybe it will help:

loading-transitions.js:52 Uncaught TypeError: Cannot read property 'nativeElement' of null(…)
LoadingMdPopIn.init @ loading-transitions.js:52
NavControllerBase._trnsStart @ nav-controller-base.js:406
(anonymous function) @ nav-controller-base.js:376
Transition.start @ transition.js:20
NavControllerBase._transition @ nav-controller-base.js:385
NavControllerBase._postViewInit @ nav-controller-base.js:295
NavControllerBase._viewTest @ nav-controller-base.js:348
NavControllerBase._nextTrns @ nav-controller-base.js:192
NavControllerBase._queueTrns.ti.resolve @ nav-controller-base.js:142
NavControllerBase._trnsFinish @ nav-controller-base.js:462
t.invoke @ polyfills.js:3
onInvoke @ ng_zone_impl.js:43
t.invoke @ polyfills.js:3
e.run @ polyfills.js:3
NgZoneImpl.runInner @ ng_zone_impl.js:70
NgZone.run @ ng_zone.js:231
(anonymous function) @ nav-controller-base.js:417
Animation._didFinish @ animation.js:511
Animation._didFinishAll @ animation.js:503
onTransitionEnd @ animation.js:207
onEvent @ dom.js:88
t.invokeTask @ polyfills.js:3
onInvokeTask @ ng_zone_impl.js:34
t.invokeTask @ polyfills.js:3
e.runTask @ polyfills.js:3
invoke @ polyfills.js:3

I tried to find a way to solve, but I was unable to solve it..... ☹

My Ionic info:

Cordova CLI: 6.3.1
Gulp version:  CLI version 3.9.1
Gulp local:
Ionic Framework Version: 2.0.0-rc.1
Ionic CLI Version: 2.1.0
Ionic App Lib Version: 2.1.0-beta.1
ios-deploy version: Not installed
ios-sim version: 5.0.8
OS: Mac OS X El Capitan
Node Version: v5.10.1
Xcode version: Xcode 8.0 Build version 8A218a
ghost commented 7 years ago

I believe this is not a dismiss() bug actually, but a wrong "this" pointer issue:

  1. One possible cause: A wrong zone (as in angular2 zone.js): Usually loader.dismiss() is called as a result of a service callback. Service callbacks might just come from "outside of angular". Which means the whole "thread local" variable context is wrong...
  2. A second option - dismiss() just might be called by a callback method with the wrong scope operator "this" - In which case you can fix by storing the right "this" pointer in a static variable and call your page methods by it (dirty - I know, but it works).
dendrochronology commented 7 years ago

What's the current consensus on the presentation/dismissal of loading spinners? The rc2 docs and this thread don't really match at all. Should we use NavController or LoadingController? Is it dismiss() or dismissAll()? How should one prevent conflicts with other navigation events?

I have a tabbed app, where each tab's data provider wants to fire a loading spinner when needed. It works fine on the home/root tab, but tapping any other tab spits out a Cannot read property 'nativeElement' of null error. I assume that means the nav action to the new tab hasn't completed before the loading controller's present() method fires off, maybe? If so, how do I tap into that, given it's an automagic event?

alouane commented 7 years ago

Hi, I don't know if you had same problem like mine, I had this Cannot read property 'nativeElement' of null error too, and problem was that I had to call this.loader = this.loadingCtrl.create({ content: "Please wait...", dismissOnPageChange: true }); this.loader.present();

Every time an event occurs. I was calling it previously inside constructor (obviously the call happens once with constructor)

Hope it helps

risleylima commented 7 years ago

I did many tests on the Loading Controller, and realized that to avoid this behavior, I had to create another instance of the object after call dismiss() on it.

I don't know if it's required, because the docs don't explain that, but, to do the same tests that I did, follow this steps:

1 - Create a new object and assign this to a window property (previously defined on a typescript description file, otherwise it will not compile):

window.testLoading =  this.loadingCtrl.create({
    content: 'Please wait...'
});

2- compile and load the app on browser.

3 - after that, it's simple, you have to call, on the console of the browser:

window.testLoading.present() -> the Loading will show correctly window.testLoading.dismiss() -> the Loading will dismiss correctly

After that, if I call the present() method on window.testLoading, I get the error: Cannot read property 'nativeElement' of null.

Here is the problem. So, if I want to call the present() method again on a Loading that I had called the dismiss() method before, I will get the error above.

To call the present() method, I had to first call the loadingCtrl to create a new instance on my window.testLoading property and only after that call the present() method.

Maybe this information will help the devs to correct the error. 😄

uzumakinaruto123 commented 7 years ago

Same in nightly version ! Calling present() in ionViewWillEnter . But , it does not happen everytime.

manucorporat commented 7 years ago

Currently, once you call ViewController.dismiss(), that ViewControler (toast, alert, actionsheet) is invalidated, you can't use it more than once.

WaveMeUp commented 7 years ago

@risleylima exactly the same behavior. As a workaround you can do this: Just create loader every time you want to use it, in my case right after modal dismissed. I'm not sure how this can make an impact on memory, but I can't find another solution for now.

constructor(public navCtrl: NavController, public modalCtrl: ModalController)
{
      this.loading = this.loadingCtrl.create({ // creating loader for the first time
        content: 'Please wait'
      });
}
showFilters() {
  let profileModal = this.modalCtrl.create(ObjectsFiltersPage);
  profileModal.onDidDismiss(() => {
    console.log('closed!')
    this.loading = this.loadingCtrl.create({ // simply create loader again after dismiss
      content: 'Please wait'
    });
    this.loadData()
  });
  profileModal.present();
}

loadData() {
  this.loading.present()
  // do something
  this.loading.dismiss()
}

ionViewDidLoad() {
  this.loadData()
}
paoesco commented 7 years ago

I have the same problem with RC4

  constructor(
      private securityContextHolder: SecurityContextHolder,
      private loadingCtrl: LoadingController,
      private navCtrl: NavController,
      private http: Http,
      fb: FormBuilder) {

     // Other inits

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

    }
    login(form: any) {
      //this.loader.present();
      if (form.valid) {
        let value = form.value;
        this.http
        .post(`${this.apiUrl}/login`, JSON.stringify(value))
        .subscribe((res: Response) => {
         // this.loader.dismiss();
          this.securityContextHolder.setCurrentUser(res.json());
          this.navCtrl.setRoot(HomePage);
        },
        (err:Response) => {
          if (err.status == 400 && err.statusText === 'user_not_enabled') {
          //  this.loader.dismiss();
            alert('Your account has not been enabled yet. Please activate it by clicking on the link provided in e-mail');
            return false;
          } else {
          //  this.loader.dismiss();
            alert('Wrong credentials');
            return false;
          }
        });
      } else {
       // this.loader.dismiss();
        alert('Required fields : email, password');
        return false;
      }

    }

This throws TypeError: Cannot read property 'nativeElement' of null at LoadingMdPopIn.init on Chrome debug console.

Thanks

ghost commented 7 years ago

The problem you are getting into, is the result of a wrong thread context - or as named by angular - zone or NgZone. Your this pointer can be null or even undefined, as happened to me and a number of other commenters above.

How to resolve:

My practice - which I guess is the way handling multithreaded code is intended to be - is handle callbacks from any of the following types of "services" (and any other suspicious service...):

  1. setTimeout( () => { ... }, X);
  2. http.get() ... then( () => ...
  3. almost any observable service involving a web worker silently underneath...

How to handle:

  1. import { NgZone } from '@angular/core';
  2. Inject the angular zone.js provider to the constructor( .... , private zone: NgZone, ... )
  3. In the callback function, returning from any of the above services - return to main/ui thread context by putting your code in: zone.run( () => { your callback code } );

Example:

setTimeout( 
    () =>
    {
        zone.run(
            () =>
            {
                // Your code now runs in the context of the main ui thread
            } );
    }, 100 );
pittdewaard commented 7 years ago

Hi all, also a litte late... but: I had the same error msg and I forgot simply to resolve(result) at my Promise in the Service ;-) maybe it will help someone...

jgw96 commented 7 years ago

Hello all! This has been fixed here https://github.com/driftyco/ionic/pull/9747 and will be in the next release. Thanks for using Ionic!

tryadelion commented 7 years ago

Is this fixed on RC5? on RC4 it's still happening, not only on the promise but just creating it.

update: in RC5 still reproducing it:

EXCEPTION: Error in ./LoginPage class LoginPage - inline template:19:4 caused by: Cannot read property 'nativeElement' of null ErrorHandler.handleError @ main.js:53150 main.js:53152 ORIGINAL EXCEPTION: Cannot read property 'nativeElement' of null ErrorHandler.handleError @ main.js:53152 main.js:53155 ORIGINAL STACKTRACE: ErrorHandler.handleError @ main.js:53155 main.js:53156 TypeError: Cannot read property 'nativeElement' of null at LoadingMdPopIn.init (main.js:103022) at OverlayPortal.NavControllerBase._trnsStart (main.js:30502) at LoadingMdPopIn._trnsStart (main.js:30468) at LoadingMdPopIn.Transition.start (main.js:14847) at OverlayPortal.NavControllerBase._transition (main.js:30485) at OverlayPortal.NavControllerBase._postViewInit (main.js:30347) at OverlayPortal.NavControllerBase._viewTest (main.js:30434) at OverlayPortal.NavControllerBase._nextTrns (main.js:30206) at OverlayPortal.NavControllerBase._queueTrns (main.js:30170) at OverlayPortal.NavControllerBase.insertPages (main.js:30028) ErrorHandler.handleError @ main.js:53156 main.js:53159 ERROR CONTEXT: ErrorHandler.handleError @ main.js:53159 main.js:53160 DebugContext_nodeIndex: 20_staticNodeInfo: (...)_tplCol: 4_tplRow: 19_view: CompiledTemplate.proxyViewClasscomponent: (...)componentRenderElement: (...)context: (...)injector: (...)providerTokens: (...)references: (...)renderNode: (...)source: (...)proto: Object ErrorHandler.handleError @ main.js:53160 main.js:1279 Uncaught ViewWrappedError

terrence0488 commented 7 years ago

I am able to reproduce this in RC4.0

Cordova CLI: 6.4.0 Ionic Framework Version: 2.0.0-rc.4 Ionic CLI Version: 2.1.17 Ionic App Lib Version: 2.1.7 Ionic App Scripts Version: 0.0.47 ios-deploy version: Not installed ios-sim version: Not installed OS: macOS Sierra Node Version: v6.9.1 Xcode version: Xcode 8.2.1 Build version 8C1002

[What I Did] create a Loading as a share instance within my component and initialise the instance in constructor. So, various part of the component will call the .present() and .dismiss() of the same instance of Loading.

[How It Happen] -> call a method and present the Loading. -> method finish the task and dismiss the Loading. -> call another method and present the Loading. x-> throw error. Cannot read property 'nativeElement' of null

[How I Resolve] Do not initialise the Loading instance in constructor. Instead, initialise it every time before I .present() it.

Its not the best thing to do in term of programming practice. I hope the Ionic team will fix this.

RobertBroersma commented 7 years ago

I'm experiencing the same issue with opening an action sheet. If I try to open the same instance for a second time I get the cannot read property nativeelement of null error. Workaround is to create a new instance everytime I want to present it. Which seems like a bad idea, but I don't know how to solve it otherwise.

danielsogl commented 7 years ago

Same problem with elements in [ngSwitch] switching by ion-segment component

lucaspalencia commented 7 years ago

Updated to version 2.0.1 and still with the error, I have a method in my service with this code:

this.loading.present();
this.http.post(this.loginUrl, JSON.stringify(requestBody), {headers: headers})
 .toPromise()
 .then(response => {
    this.auth.authLogin(type, userInfo.usuario, response.json().token);
 })
 .catch(response => {
    this.loading.dismiss();
 });

The first time that my http.post executed this.loading.dismiss(); everything works ok, but if i try again the console returns the error:

Cannot ready property 'nativeElement' of null

Some help?

malick7 commented 7 years ago

@lucaspalencia I re-initialized the loading controller object everytime, we make a http.post and it worked for me. See if it works for you. loading = this.loadingCtrl.create({ content: 'Loading' }); init(){ this.loading = this.loadingCtrl.create({ content: 'Loading' }); }

And inside your http call, do this!

doHttpPost (){ this.init(); this.loading.present(); this.http.post(this.loginUrl, JSON.stringify(requestBody), {headers: headers}) .toPromise() .then(response => { this.auth.authLogin(type, userInfo.usuario, response.json().token); }) .catch(response => { this.loading.dismiss(); }); }

Cheers!

patrickmar commented 7 years ago

also experiencing same issue in ionic 2

lucaspalencia commented 7 years ago

@malick7

I was creating loadingController with a variable in the begin of my service and after in my method executing present() and dismiss().

Now i add the .create before the present() into my method and works well. Thank you!

charIeszhao commented 7 years ago

@malick7 Thank you! I have the same issue and now it works.

Hope the ionic team can fix this trivial defect as it's really not a good programming practice to initialize a new instance before calling present() method.

shogunfighter commented 7 years ago

I think you need to kill the instance of the loading class before reusing it again. That's why it's throwing errors.

Here, you can plug this provider/service if you want. I just edited this...


/**
 * Usage:
 *  
 *  //create loading service instance
 *  private loadingSvc:LoadingService;
 *  
 *  //this is how you show the loading instance
 *  loadingSvc.show("someRandomNameOfTheLoading","Message in the Loading instance");
 *  
 *  
 *  setTimeout(
 *  () => {
 *  
 *      //this is an example of how you kill the loading instance
 *      loadingSvc.hide("someRandomNameOfTheLoading");
 *  },
 *  2000
 *  )
 */

import {Injectable} from '@angular/core';
import {LoadingController, Loading} from 'ionic-angular';

@Injectable()
export class LoadingService {

    private loaderList:Array<Loading> = [];

    constructor(private loadingCtrl:LoadingController) {
        console.log('Hello LoadingService Provider');
    }

    /**
     * Creates a loading instance and present it
     * @param id
     * @param msg
     */
    public show(id, msg = 'Please wait...') {
        if(!this.loaderList[id]) this.loaderList[id] = this.loadingCtrl.create({
            content: msg
        });

        this.loaderList[id].present();
    }

    /**
     * Hide and then automatically remove the loading instance
     * @param id
     * @returns {Promise<any>}
     */
    public hide(id) {
        let prom = this.loaderList[id].dismiss();
            prom.then(
                ()=> { this.remove(id); }
            );

        return prom;
    }

    /**
     * Call `remove` to manually remove the loading instance
     * @param id
     */

    //normally you don't manually use this method, better use the method -> hide()
    public remove(id) {
        delete this.loaderList[id];
        console.log("this.loaderList:",this.loaderList);
    }

}

I have been using this loading PROVIDER, just modify it to your specifications if you like...

FernandoX7 commented 7 years ago

Still happening on latest version