Converting Gmail API integration to work with Vue.js framework

I’m trying to integrate Gmail API into my Vue.js project but having trouble adapting the vanilla JavaScript code to work properly with Vue components. I found a working example in plain HTML/JS but need help converting it to Vue syntax.

<template>
  <div>
    <h2>Email API Integration</h2>
    <button v-if="!isAuthenticated" @click="authenticate">Login</button>
    <button v-if="isAuthenticated" @click="logout">Logout</button>
    <div v-if="emailData" class="email-list">
      <h3>Inbox Labels:</h3>
      <ul>
        <li v-for="item in emailData" :key="item.id">{{ item.name }}</li>
      </ul>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      apiKey: 'YOUR_API_KEY_HERE',
      clientId: 'YOUR_CLIENT_ID_HERE',
      discoveryUrls: ['https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest'],
      permissions: 'https://www.googleapis.com/auth/gmail.readonly',
      isAuthenticated: false,
      emailData: null
    }
  },
  methods: {
    initializeGapi() {
      gapi.load('client:auth2', this.setupClient)
    },
    setupClient() {
      gapi.client.init({
        apiKey: this.apiKey,
        clientId: this.clientId,
        discoveryDocs: this.discoveryUrls,
        scope: this.permissions
      })
    },
    authenticate() {
      gapi.auth2.getAuthInstance().signIn()
    },
    logout() {
      gapi.auth2.getAuthInstance().signOut()
    },
    fetchLabels() {
      gapi.client.gmail.users.labels.list({
        userId: 'me'
      }).then(response => {
        this.emailData = response.result.labels
      })
    }
  }
}
</script>

Can someone help me figure out the proper way to structure this in Vue and handle the authentication flow correctly?

The main issue is you’re not handling the GAPI lifecycle properly with Vue’s component lifecycle. I hit the same problem when I first tried this integration last year. Here’s what you need to fix: Initialize GAPI in the mounted hook and set up auth state listeners properly. Add a mounted() hook that calls initializeGapi(). You’re missing the auth state change listener - after your gapi.client.init() call in setupClient(), add: gapi.auth2.getAuthInstance().isSignedIn.listen(this.updateAuthStatus). Create an updateAuthStatus method that sets this.isAuthenticated based on current state. Your authenticate method should handle the promise from signIn() to catch errors. Call fetchLabels() after successful auth. Your current structure will work but won’t auto-update the UI when auth state changes.

Your code structure’s mostly right, but you’ve got a timing issue with the auth flow. I ran into the same problem when I did this integration - the auth state isn’t tracked properly from the start. After gapi.client.init() resolves, immediately check if the user’s already signed in with gapi.auth2.getAuthInstance().isSignedIn.get() and update your isAuthenticated property. Also, your authenticate() method should return the promise so you can chain fetchLabels() after auth succeeds. Wrap your GAPI calls in try-catch blocks too - the Gmail API throws different errors depending on user permissions and network issues. Your discovery URL and scope look good for readonly access though.

you’re missing the gapi script import in your HTML head. your setupClient method also needs async/await or .then() to handle the promise properly. I ran into the same thing - definitely add error handling for auth since it fails silently half the time.