Util Events: Cannot set property 'events' of undefined

Hi! I’ve been using Events for a while but in the past week I started to get this critical error in the browser console when using them. As soon as I .publish() a new event I get these errors:

Runtime Error
Uncaught (in promise): TypeError: Cannot set property 'events' of undefined TypeError: Cannot set property 'events' of undefined at MyApp (http://localhost:8100/build/main.js:1283:21) at AppModuleInjector.get (ng:///AppModule/module.ngfactory.js:266:71) at AppModuleInjector.getInternal (ng:///AppModule/module.ngfactory.js:432:54) at AppModuleInjector.NgModuleInjector.get (http://localhost:8100/build/vendor.js:4084:44) at resolveDep (http://localhost:8100/build/vendor.js:11546:45) at createClass (http://localhost:8100/build/vendor.js:11405:147) at _createProviderInstance (http://localhost:8100/build/vendor.js:11369:26) at Object.resolveDep (http://localhost:8100/build/vendor.js:11526:53) at Injector_.get (http://localhost:8100/build/vendor.js:10850:25) at ReflectiveInjector_._getByKeyDefault (http://localhost:8100/build/vendor.js:3313:24)
Stack
Error: Uncaught (in promise): TypeError: Cannot set property 'events' of undefined
TypeError: Cannot set property 'events' of undefined
    at MyApp (http://localhost:8100/build/main.js:1283:21)
    at AppModuleInjector.get (ng:///AppModule/module.ngfactory.js:266:71)
    at AppModuleInjector.getInternal (ng:///AppModule/module.ngfactory.js:432:54)
    at AppModuleInjector.NgModuleInjector.get (http://localhost:8100/build/vendor.js:4084:44)
    at resolveDep (http://localhost:8100/build/vendor.js:11546:45)
    at createClass (http://localhost:8100/build/vendor.js:11405:147)
    at _createProviderInstance (http://localhost:8100/build/vendor.js:11369:26)
    at Object.resolveDep (http://localhost:8100/build/vendor.js:11526:53)
    at Injector_.get (http://localhost:8100/build/vendor.js:10850:25)
    at ReflectiveInjector_._getByKeyDefault (http://localhost:8100/build/vendor.js:3313:24)
    at c (http://localhost:8100/build/polyfills.js:3:13190)
    at Object.reject (http://localhost:8100/build/polyfills.js:3:12546)
    at NavControllerBase._fireError (http://localhost:8100/build/vendor.js:46340:16)
    at NavControllerBase._failed (http://localhost:8100/build/vendor.js:46328:14)
    at http://localhost:8100/build/vendor.js:46383:59
    at t.invoke (http://localhost:8100/build/polyfills.js:3:8971)
    at Object.onInvoke (http://localhost:8100/build/vendor.js:4656:37)
    at t.invoke (http://localhost:8100/build/polyfills.js:3:8911)
    at r.run (http://localhost:8100/build/polyfills.js:3:4140)
    at http://localhost:8100/build/polyfills.js:3:13731

Ionic Framework: 3.5.0
Ionic App Scripts: 2.0.1
Angular Core: 4.1.3
Angular Compiler CLI: 4.1.3
Node: 8.1.3
OS Platform: Windows 10
Navigator Platform: Win32
User Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1

Here’s some code of how I use it:

import { Component } from '@angular/core';
import {
  IonicPage,
  Events
} from 'ionic-angular';
import { UserService } from '../../providers/user-service';

@IonicPage()
@Component({
  selector: 'page-sign-in',
  templateUrl: 'sign-in.html'
})

export class SignInPage {
  username: any;
  password: any;

  constructor(
    public toastCtrl: ToastController,
    public events: Events,
    public userService: UserService
  ) {
  }

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

  submit(event) {
    if ((this.username) && (this.password)) {
      this.userService.authenticate(this.username, this.password).subscribe((data: any) => {
        if (data.token) {
          // preparing authData
          this.userService.authData = {
            userId: data.userId,
            username: data.username,
            token: data.token
          }
          this.events.publish('user:login'); // TRIGGERS THE ERROR
        } else {
          alert('Invalid username and/or password!');
        }
      });
    } else {
      alert('Fill username & password fields first!');
    }
    event.stopPropagation();
  }
}

I don’t try to set anything anywhere I’m just publishing an event. this.events isn’t even null:

It looks like it might be a bug to me but I want to ask here before opening an issue on GitHub. Anyone has an idea of what’s going on here?

Thanks!

Okay weird thing here. I moved the publish event for fun right in the beginning of the submit function:

  submit(event) {
    this.events.publish('user:login'); // this one works
    if ((this.username) && (this.password)) {
      this.userService.authenticate(this.username, this.password).subscribe((data: any) => {
        if (data.token) {
          // preparing authData
          this.userService.authData = {
            userId: data.userId,
            username: data.username,
            token: data.token
          }
          // authData should be persisted through sessions
          this.userService.saveAuthData();
          // welcoming user and spamming login event
          this.displayWelcomeMessage(data.username);
          this.events.publish('user:login'); // this one doesn't
        } else {
          alert('Invalid username and/or password!');
        }
      });
    } else {
      alert('Fill username & password fields first!');
    }
    event.stopPropagation();
  }

I even tried retaining this with const self = this and replacing all inner this with self but it still does the same errors. I’ll keep digging but that’s one big clue right here :smile:

What is actually causing this is the this.displayPlayer = true; call!!!

I have a <ion-footer *ngIf="displayPlayer"> in the html section.

And also
this.rootPage = PodcastListPage;
switching to another page makes the same errors.

Now I gotta figure out why but at least I now know that it’s not a bug and it’s my fault!