0

I am new to ionic, I want to test a firebase login and handle it (wrong password, user not found etc...). The problem is when I click the login button it always tells me ERROR TypeError: Cannot read property 'toastController'. I tried to look at other post but I didn't found where does the problem comes from. The full error :

vendor.js:1703 ERROR TypeError: Cannot read property 'toastController' of 
undefined(…)defaultErrorLogger @ vendor.js:1703
ErrorHandler.handleError @ vendor.js:1764
IonicErrorHandler.handleError @ vendor.js:122703
next @ vendor.js:5729
schedulerFn @ vendor.js:4576
SafeSubscriber.__tryOrUnsub @ vendor.js:32170
SafeSubscriber.next @ vendor.js:32117
Subscriber._next @ vendor.js:32057
Subscriber.next @ vendor.js:32021
Subject.next @ vendor.js:39739
EventEmitter.emit @ vendor.js:4556
(anonymous function) @ vendor.js:5004
t.invoke @ polyfills.js:3
r.run @ polyfills.js:3
NgZone.runOutsideAngular @ vendor.js:4930
onHandleError @ vendor.js:5004
t.handleError @ polyfills.js:3
r.runTask @ polyfills.js:3
e.invokeTask @ polyfills.js:3
i.isUsingGlobalCallback.invoke @ polyfills.js:3
n @ polyfills.js:3

The error is thrown in the login function.

export class HomePage {
  user = {} as User;

  constructor(private toastController: ToastController, private afAuth: AngularFireAuth, public navCtrl: NavController) {

  }

  async login(user: User){
    try {
      const result = this.afAuth.auth.signInWithEmailAndPassword(user.email, user.password)
      .catch(function(error) {
        // Handle Errors here.
        var errorCode = error.code;
        var errorMessage = error.message;
        var foo;
        if (errorCode === 'auth/wrong-password') {
          foo = {
            message: 'Wrong password',
            duration: 3000,
            position: 'bottom'
          };
        } else if (errorCode === 'auth/user-not-found') {
          foo = {
            message: 'User not found',
            duration: 3000,
            position: 'bottom'
          };
        }
        else
        {
          foo = {
            message: errorMessage,
            duration: 3000,
            position: 'bottom'
          };
        }

        this.toastController.create(foo).present();
      });
    } catch (error) {
      //console.log(error.N);
    }

  }

  register(){
    this.navCtrl.push("RegisterPage");
  }
}

Thanks in advance for the help

Sébastien
  • 10,675
  • 11
  • 47
  • 67
Antoine D
  • 89
  • 1
  • 9
  • You don't have anythings else to do that marking duplicated post (This one is not)? You lives must be nice... – Antoine D Jan 26 '18 at 14:42

1 Answers1

2

The question When should I use Arrow functions in ECMAScript 6? contains a clue to fixing your problem.

You have to understand the different behavior of functions declared with the function keyword on the one hand, and "arrow" functions on the other hand.

In your catch() callback you use:

.catch(function(error) {
    // ...
})

The classical JavaScript function syntax create a new execution context and binds this to it. That's why later in your function when you call:

this.toastController.create(foo).present();

this is no longer referrring to your class, but to the function itself, and there is obviously no toastController property in that function, so your are calling create() on an undefined property, hence the error message.

ERROR TypeError: Cannot read property 'toastController'

If you use the arrow function syntax in your callback, no new context will be created inside the function, and this will refer to the outer context: that of the class.

.catch((error) => {
    // ...
})

I also recommend you read: ES6 In Depth: Arrow functions.

Sébastien
  • 10,675
  • 11
  • 47
  • 67