Suraj Khanal
Suraj Khanal

Reputation: 540

How to access methods inside object in vuejs?

I am trying to make login with google in vue by following google document and everything worked but i cant access method inside attachClickHandler.

new Vue({
    el: '#loginModal',
    data: { ...
    },
    methods: {
        gInit: function() {
            gapi.load('auth2', function() {
                auth2 = gapi.auth2.init({
                    client_id: 'MY-Client-id.apps.googleusercontent.com',
                    cookiepolicy: 'single_host_origin',
                    //scope: 'additional_scope'
                });
                auth2.attachClickHandler(document.getElementById('googleBtn'), {},
                    function(googleUser) {
                        const profile = googleUser.getBasicProfile();
                        const gplusObj = {
                            name: profile.getName(),
                            email: profile.getEmail(),
                            provider: 'google',
                            image: profile.getImageUrl(),
                            provider_user_id: profile.getId()
                        };

                        this.socialLogin(gplusObj);
                    },
                    function(error) {
                        alert(JSON.stringify(error, undefined, 2));
                    });
            });
        },
        socialLogin: function(data) {
            axios.post(`${this.api}/api/sociallogin`, data)
                .then(res => {
                    console.log(res);
                }).catch(err => {
                    console.log(err);
                });
        },
    },
    mounted: function() {
        this.gInit();
    }

})

Here calling a function socialLogin() inside attachClickHandler() is giving error this.socialLogin is not a function is not defined. Why this is not working?

Upvotes: 1

Views: 238

Answers (2)

xianshenglu
xianshenglu

Reputation: 5329

Because you didn't save this,try :

new Vue({
  el: '#loginModal',
  data: { ...
  },
  methods: {
    gInit: function() {
      let self = this // new added
      gapi.load('auth2', function() {
        auth2 = gapi.auth2.init({
          client_id: 'MY-Client-id.apps.googleusercontent.com',
          cookiepolicy: 'single_host_origin',
          //scope: 'additional_scope'
        });
        auth2.attachClickHandler(document.getElementById('googleBtn'), {},
          function(googleUser) {
            const profile = googleUser.getBasicProfile();
            const gplusObj = {
              name: profile.getName(),
              email: profile.getEmail(),
              provider: 'google',
              image: profile.getImageUrl(),
              provider_user_id: profile.getId()
            };
            console.log(e);
            self.socialLogin(gplusObj); //updated
          },
          function(error) {
            alert(JSON.stringify(error, undefined, 2));
          });
      });
    },
    socialLogin: function(data) {
      axios.post(`${this.api}/api/sociallogin`, data)
        .then(res => {
          console.log(res);
        }).catch(err => {
          console.log(err);
        });
    },
  },
  mounted: function() {
    this.gInit();
  }

})

this wouldn't be passed automatically and you should already know this before learning vue.

Also,you can use arrow function to avoid this being changed:

new Vue({
  el: '#loginModal',
  data: { ...
  },
  methods: {
    gInit: function() {
      gapi.load('auth2', function() {
        auth2 = gapi.auth2.init({
          client_id: 'MY-Client-id.apps.googleusercontent.com',
          cookiepolicy: 'single_host_origin',
          //scope: 'additional_scope'
        });
        auth2.attachClickHandler(document.getElementById('googleBtn'), {},
          (googleUser) => { //updated
            const profile = googleUser.getBasicProfile();
            const gplusObj = {
              name: profile.getName(),
              email: profile.getEmail(),
              provider: 'google',
              image: profile.getImageUrl(),
              provider_user_id: profile.getId()
            };
            console.log(e);
            this.socialLogin(gplusObj);
          },
          function(error) {
            alert(JSON.stringify(error, undefined, 2));
          });
      });
    },
    socialLogin: function(data) {
      axios.post(`${this.api}/api/sociallogin`, data)
        .then(res => {
          console.log(res);
        }).catch(err => {
          console.log(err);
        });
    },
  },
  mounted: function() {
    this.gInit();
  }

})

Upvotes: 0

sandrooco
sandrooco

Reputation: 8716

It's because the this.socialLogin call is located in a callback function. This function creates a new context so this changes and won't be your component anymore. Use arrow functions. They won't change this.

Edit: Change your code like this:

gInit() {
    gapi.load('auth2', () => {
        ...
        auth2.attachClickHandler(document.getElementById('googleBtn'), {}, (googleUser) => {
            ...
            this.socialLogin(gplusObj);
        }, (error) => {
            alert(JSON.stringify(error, undefined, 2));
        });
    });
},

More on that topic: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions, see "No separate this".

Upvotes: 2

Related Questions