ashishtomer
ashishtomer

Reputation: 316

Component variable can't be modified in a callback method in vue.js

I defined a Login.vue component in the vue.js that let's me login the user to my application through AWS Cognito. I use the ___.authenticateUser() method to login the user and start a session with Cognito. Below is the actual code that does so:

export default {
  name : 'Login',
  data: function() {
    return {
      errorMessageHidden: true,
      formHidden: false,
      errorMessage: '',
      email: '',
      password: ''
    }
  },
  methods: {
    showValuesToMe: function() {
      console.log(this.errorMessageHidden)
    },
    handleLogin: function() {
      const data = {
        Username: this.email,
        Pool: userPool
      }

      const cognitoUser =  new CognitoUser(data);

      const authenticationData = {
        Username : this.email,
        Password : this.password,
      };

      function showErrorMessage(err) {
        this.errorMessageHidden = false;
        this.errorMessage = err.message;
        console.log("The method got called... errorMessageHidden = " + this.errorMessageHidden);
      }

      const authenticationDetails = new AuthenticationDetails(authenticationData)

      cognitoUser.authenticateUser(authenticationDetails, {
        callback: showErrorMessage,
        onSuccess: function(result) {
          console.log('access token ' + result.getAccessToken().getJwtToken());
        },
        onFailure: function(err) {
          this.callback(err);
        }
      });
    },

    hideErorrMessage: function() {
      this.errorMessageHidden = true;
    }
  }
}

The issue is, inside the handleLogin() function of the component, when ___.authenticateUser() is called Cognito SDK calls either onSuccess() or onFailure() depending on the auth result from the AWS.

Inside the onFailure() when I try to modify the errorMessageHidden and errorMessage they can't be! It happens because the onFailure() method is a callback method and a closure.

To access/modify these values I defined the function showErrorMessage(err) {...} in the scope of closure's parent. Now I can access the values defined in data but still can't modify them.

Can anyone figure it out how I can change the values to make changes and show error in the browser.

Upvotes: 1

Views: 1053

Answers (2)

mjfakhr
mjfakhr

Reputation: 21

This worked for me:

Function in the this components:

BusEvent.$emit("CloseAllTab",check => {
  if(check == true){
    this.isShowSelectYearActive = true;
  }
});

Function in the other components:

methods: {
  CloseAllTab(check) {
    check(true);
  }
},
created() {
  BusEvent.$on("CloseAllTab",this.CloseAllTab);
},
beforeDestroy() {
  BusEvent.$on("CloseAllTab",this.CloseAllTab);
}

Upvotes: 1

Hector Romero Granillo
Hector Romero Granillo

Reputation: 286

Your problem is because you are using function instead of arrow functions for your callback functions. When you create a function using function a new scope is created and this is not your Vue Component anymore.

You want to do it like this:

handleLogin: function() {
      const data = {
        Username: this.email,
        Pool: userPool
      }

      const cognitoUser =  new CognitoUser(data);

      const authenticationData = {
        Username : this.email,
        Password : this.password,
      };

      const showErrorMessage = err => {
        this.errorMessageHidden = false;
        this.errorMessage = err.message;
        console.log("The method got called... errorMessageHidden = " + this.errorMessageHidden);
      }

      const authenticationDetails = new AuthenticationDetails(authenticationData)

      cognitoUser.authenticateUser(authenticationDetails, {
        callback: showErrorMessage,
        onSuccess: result => {
          console.log('access token ' + result.getAccessToken().getJwtToken());
        },
        onFailure: err => {
          this.callback(err);
        }
      });
    }

With arrow functions, you will maintain the scope of the function that is calling it, so if you are inside a Vue method and use an arrow function, inside the arrow function this will still be the Vue Component.

Just beware, you cannot use arrow functions as a direct property of the methods object. That is because Vue needs to invoke the function with the Vue Component bound to this, something that cannot be done with arrow functions. But besides that, you may want to start using arrow function everywhere you can, they are one of my favorite ES5 features.

Upvotes: 6

Related Questions