A guide on incorporating Google authentication into Vue.js with the use of TypeScript and the component-based syntax

Currently, I am in the process of integrating Google authentication into my Vue.js front end. The project was initialized using CLI with TypeScript and component style syntax enabled, alongside other configurations. Additionally, there is a backend web server associated with this project. Despite being new to Vue.js and gapi, I have been following this guide provided by Google. However, I am unsure about how to load

<script src="https://apis.google.com/js/platform.js" async defer></script>
into my application and utilize it once loaded. Although I have come across examples like this one on jsfiddle, as well as some incomplete solutions on Stack Overflow and various forums, none seem to cater specifically to TypeScript and component style syntax.

Here are snippets from different parts of the project:

<template>
  <div id="app">
    <div id="nav">
      <router-link to="/">Login</router-link>
    </div>
    <router-view />
  </div>
</template>

<style lang="scss">
</style>

Main.ts

import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";

Vue.config.productionTip = false;

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount("#app");

Login.vue (View)

<template>
  <div>
    <Login />
  </div>
</template>

<script>
// @ is an alias to /src
import Login from "@/components/Login.vue";

export default {
  name: "login",
  components: {
    Login
  }
};
</script>

Login.vue (Component)

<template>
  <div>
    <button>Sign in with Google</button>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";

@Component
export default class Login extends Vue {}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
</style>

Answer №1

To incorporate Google sign-in functionality, you must insert the Google sign-in script into the index.html file located in the public directory.

Ensure that you include it in the head section without using async or defer mode.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
    <title><%= htmlWebpackPlugin.options.title %></title>
    <script src="https://apis.google.com/js/api:client.js"></script>
  </head>
  <body>
    <noscript>
      <strong
        >We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
        properly without JavaScript enabled. Please enable it to
        continue.</strong
      >
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

Next, within your login.vue file

<template>
  <div>
    <button class="g-signin-button">Sign in with Google</button>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";
@Component
export default class Login extends Vue {
  clientId = "AIzaSyBRxykObiOjM7VsY_lyGcRU27q8aFeAagk";
  mounted() {
    if (!window.gapi) {
      throw new Error(
        '"https://apis.google.com/js/api:client.js" needs to be included as a <script>.'
      );
    }

    // more logic here...
    
  }
  
  methods() {
    function err(msg: string) {
      typeof console !== "undefined" &&
        console.error(`[g-signin-button] ${msg}`);
    }
  }
}
</script>

<style scoped lang="scss">
.g-signin-button {
  box-sizing: border-box;
  position: relative;
  /* CSS styles */
}

// More SCSS styles...

</style>

Since the gapi is installed at the window level and for TypeScript support, external npm packages are required for types.

npm i -D @types/gapi @types/gapi.auth2

Remember to include these types in the "types" key of your tsconfig.json.

"types": ["webpack-env", "gapi", "gapi.auth2"],

I hope this information proves beneficial!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Running various IT blocks within a Protractor loop to enhance web testing

After logging in to a web page, we need to use a for loop to perform multiple tests on the page. The ideal test scenario involves a table with buttons on each row that leads to another page where data needs to be validated. Currently, all expectations and ...

Having trouble accessing a DOM element within a Vue component while using vanilla JavaScript

I am attempting to dynamically update data from a Vue component using jQuery in a Webpack project. Below is the code snippet: <template> <div id="container"> <slot>show string!!</slot> <div id="s_container"&g ...

How can I retrieve the object returned by an external API in VueJS?

I recently integrated the hcaptcha widget into my login component by utilizing the following package: https://github.com/hCaptcha/vue-hcaptcha. The challenge is functioning correctly on the front end. Upon inspecting the response object in the network tab ...

Tips for renaming input file before uploading to a new destination

Instead of using the original name, I would like to replace the image that the user wants to upload with my own pattern. I understand that it's preferable to change the file name on the server, but unfortunately, I am unable to do so for certain reaso ...

What is the best way to display the nested information from products.productId?

How do I display the title and img of each product under the product.productId and show it in a table? I attempted to store the recent transaction in another state and map it, but it only displayed the most recent one. How can I save the projected informa ...

Having issues with Craco not recognizing alias configuration for TypeScript in Azure Pipeline webpack

I am encountering an issue with my ReactJs app that uses Craco, Webpack, and Typescript. While the application can run and build successfully locally, I am facing problems when trying to build it on Azure DevOps, specifically in creating aliases. azure ...

The attribute 'disabled' is originally defined as a characteristic within the class 'CanColor & CanDisableRipple & HasTabIndex & MatChipBase'. However, it is replaced in the current context of 'MatChip' as an attribute

After updating my Angular version from 9.1 to 11, I encountered a compilation error. Error: node_modules/@angular/material/chips/chips.d.ts:120:9 - error TS2611:'disabled' is defined as a property in class 'CanColor & CanDisableRipple &a ...

What exactly does the dollar sign signify in plain JavaScript code?

While watching a tutorial on object literals in JavaScript, I noticed something interesting. The instructor demonstrated creating an object like this: var Facebook = { name: 'Facebook', ceo: { firstName: "Mark", favColor: ...

Changing the port of an https (http) URL: A step-by-step guide

Initially, I have a website set up on nginx and Ubuntu 20.04 running on port 80 for http and port 443 for https, accessible through the URL https://mysite.cc (It is functioning correctly). Now, I am looking to add another site using Spring Cloud (Docker) ...

The dependencies were not updated after running `npm install`

When attempting to update the dependencies in my react-native CLI app by running npm install for the package.json, I encountered issues. Subsequently, I tried using npm audit fix and npm audit fix --force without success. In an effort to resolve the probl ...

Exploring the wonders of v-for with JSON data: A step-by-step guide

I am attempting to utilize v-for in order to dynamically generate <li> elements by retrieving data from a JSON file. Here is my code, where the JSON data is stored in a variable named urls. <script> const urls =[ {text:'math&a ...

Customizing the color scheme of specific components using Material UI inline styling

I am currently customizing my TextFields from Material-UI. My background is black and I want both the textField border and text to be white. Here's the relevant part of my code: render() { const styles = { width: { width: '90%& ...

Choose the list item below

I'm working on a website that includes a select list with images. Here's what I have so far: When I choose an image from the list, it should display below. <?php // Establish database connection $con=mysqli_connect("******","***","*** ...

Utilize JavaScript and jQuery to extract the selected text's context from a webpage

I'm looking to extract the contextual information surrounding a selected text on a web page, specifically the 25 words before and after it. I've tried using JavaScript and jQuery with the following code snippet but unfortunately, it doesn't ...

A comprehensive guide on displaying data in Angular using an API

I have encountered an issue while trying to display data from an API in the 'home.component.html'. Although my 'home.component.ts' successfully fetches the data from the service, I'm facing difficulty rendering it in 'home.com ...

Issue with TypeORM findOne method causing unexpected output

I am encountering an issue with my User Entity's Email Column when using TypeORM's findOne function. Instead of returning null for a non-existent email, it is returning the first entry in the User Entity. This behavior does not align with the doc ...

Generate a new array of objects by cloning an existing array of objects with placeholder values

I am looking to transform an array of objects into another array of objects in order to generate a graph. Below is the array I am using to determine the position of each object within the new object. let uniqueSkills = ['Using', 'Analyzing ...

Encountered a SyntaxError on JSON Web Tokens Node JS Server: Unexpected token } found in JSON at position 24

Me, along with others, have encountered this issue: SyntaxError: Unexpected token } in JSON at position 24 at JSON.parse (<anonymous>) while following a tutorial on JSON Web Tokens (TUTORIAL LINK: https://www.youtube.com/watch?v=mbsmsi7l3r4&t=34s ...

Having trouble with the import of the directory's index file?

The code snippet in application.js indicates that the "home" imported from "./routes/index" is undefined. import {home} from "./routes/index" console.log(JSON.stringify(home, null, 4)) This is what index.js contains: export * from "./home.js" And here ...

Is there a way I can finish animating these divs in a diagonal motion?

I successfully made the blue and red divs move diagonally and switch positions. Now I am looking to achieve the same effect with the green and pink divs using a similar function. I am unsure about setting the position of both divs to 0 and 350 for those p ...