Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot read property 'navCtrl' of undefined

For hours I've been searching for a solution to this problem in my project to no avail. I've read many of the other "Cannot read property ... of undefined" posts, but can't seem to find a solution for mine.

Below is the relevant code in my project.

This is an Ionic 2 / Apache Cordova project and the page below is the Sign In Page for the app. It is not one of the core app components, it is simply a regular page.

For some reason, the NavController is not being recognized in the onSignIn() method, but I have no idea why. I've injected NavController in the constructor, and it doesn't look like I am failing to follow any known procedure that I am aware of, but it's still failing every time.

import firebase from 'firebase';
import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { HomePage } from './../home/home';

var provider = new firebase.auth.FacebookAuthProvider();

@Component({
  selector: 'page-signin',
  templateUrl: 'signin.html',
})

export class SignInPage {

  constructor(public navCtrl: NavController, public params: NavParams) {}

  onSignIn() {
    firebase.auth().signInWithPopup(provider).then(function(result) {
      console.log(result.credential.accessToken);
      console.log(result.user.displayName);
      this.navCtrl.setRoot(HomePage);
    }).catch(function(error) {
      console.log(error.message);
    });
  }
}
like image 829
Aaron Viscichini Avatar asked Mar 10 '23 08:03

Aaron Viscichini


2 Answers

A better way to solve this issue would be by using arrow functions:

An arrow function expression has a shorter syntax than a function expression and does not bind its own this, arguments, super, or new.target.

So your issue would be solved by just changing the onSignIn method like this:

  onSignIn() {
    firebase.auth().signInWithPopup(provider).then((result) => {
      console.log(result.credential.accessToken);
      console.log(result.user.displayName);
      this.navCtrl.setRoot(HomePage);
    }).catch(function(error) {
      console.log(error.message);
    });
  }

Notice the (result) => {...} instead of the function(result) {...}

like image 93
sebaferreras Avatar answered Mar 19 '23 11:03

sebaferreras


try like the below code:

let _this;

@Component({
  selector: 'page-signin',
  templateUrl: 'signin.html',
})

export class SignInPage {

  constructor(public navCtrl: NavController, public params: NavParams) {
    _this = this; //Either here or in onSignIn whichever called first
  }

  onSignIn() {
    _this = this; //Either here or in constructor whichever called first
    firebase.auth().signInWithPopup(provider).then(function(result) {
      console.log(result.credential.accessToken);
      console.log(result.user.displayName);
      _this.navCtrl.setRoot(HomePage);
    }).catch(function(error) {
      console.log(error.message);
    });
  }
}

I think you are facing the problem because of the scope of this. In your case scope of this belongs to the function which is passed inside then.

like image 37
Prerak Tiwari Avatar answered Mar 19 '23 11:03

Prerak Tiwari