Using Vue SPA to bind single file components with Stripe Elements

Attempting to integrate Stripe Elements into a Vue SPA single file component has presented me with a challenge in the form of this error:

IntegrationError: Missing argument. Make sure to call mount() with a valid DOM element or selector.
    at new t (https://js.stripe.com/v3/:1:10765)
    at t.<anonymous> (https://js.stripe.com/v3/:1:97008)
    at t.<anonymous> (https://js.stripe.com/v3/:1:26038)
    at VueComponent.createCardElement (webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/components/stripe/card-modal.vue?vue&type=script&lang=js&:143:17)
    at VueComponent.stripePubKey (webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader/lib/index.js?!./src/components/stripe/card-modal.vue?vue&type=script&lang=js&:177:14)
    at Watcher.run (webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js:4562:19)
    at flushSchedulerQueue (webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js:4304:13)
    at Array.eval (webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js:1979:12)
    at flushCallbacks (webpack-internal:///./node_modules/vue/dist/vue.runtime.esm.js:1905:14)

The issue arises during the execution, specifically failing at the .mount() function due to an absence of a valid DOM element/selector.

Here is the summary of methods I have experimented with:

  1. The code executes after the component's lifecycle (My component is structured as a Buefy modal, triggering the stripe element mount logic when the modal becomes visible).
  2. The code runs immediately following Stripe's official Vue example.
  3. The code executes right after the 'stripePubKey' property ceases to be null (Noting that the 'stripePubKey' is updated within the mounted segment of the Vue lifecycle).

Below is the snippet for the component once scenario 3 unfolds:

<template>
    <div>
        <b-button class="button is-info is-rounded"
                  size="is-medium"
                  icon-left="credit-card"
                  :loading="isLoading" 
                  @click="isModalActive = true" v-if="!cardId">
            Add a card
        </b-button>
        <button class="button is-warning"
                :loading="isLoading"
                @click="isModalActive = true" v-else>
            Edit
        </button>

        <b-modal has-modal-card trap-focus :active.sync="isModalActive">
            <b-loading :active.sync="isModalLoading" :can-cancel="false" />
            <form v-on:submit.prevent="create()" class="has-text-justified">
                <div class="modal-card">
                    <header class="modal-card-head">
                        <p class="modal-card-title" v-if="!cardId">Add a card</p>
                        <p class="modal-card-title" v-else>Edit a card</p>
                    </header>
                    <section class="modal-card-body">
                        <div ref="cardo"></div>
                        <p v-show="elementsError" id="card-errors" v-text="elementsError" />
                    </section>

                    <footer class="modal-card-foot">
                        <button class="button" type="button" @click="isModalActive = false">Close</button>
                        <button class="button is-primary" type="submit" :disabled="!complete">Add</button>
                    </footer>
                </div>
            </form>
        </b-modal>
    </div>
</template>

... <!-- Skipping the script section for brevity -->

In addition, the aforementioned component attempts to mount the card element using $refs, even though the official Stripe VueJS sample uses '#card-element' for the same purpose. Both methods were tested without success!

For reference, here is my index.html for the SPA which includes the Stripe script placement:

<!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">
    <link href="https://fonts.googleapis.com/css?family=Roboto:100:300,400,500,700,900|Material+Icons" rel="stylesheet">
    <title>Nozomi</title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but Nozomi 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>
  <script src="https://js.stripe.com/v3/"></script>
</html>

Answer №1

The reason for the issue is that the buefy model is not present in the dom until it is opened and rendered.

To solve this, instead of directly setting isModalActive to true, create a method to open it and initialize the stripe element in the next tick. This will guarantee that the dom element is properly rendered.

methods: {
    openModal() {
        this.isModalActive = true;
        this.$nextTick(function () {
            this.createCardElement()
        })
    }
}

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

Guide on how to trigger a pop-up modal to open a new webpage by clicking on a hyperlink

I have a page called one.html that has a link on it <a href="#">Click to open second page<a/> When this link is clicked, I would like for second.html to open in a popup modal. The second page contains a basic table that I want to di ...

Configuring routes for Angular4 router is a vital step in creating a

Issue: I am currently setting up routes for my application, aiming to structure the URL as https://localhost:4200/hero=id, where the 'id' will be dynamically selected. However, this setup is not functioning as expected. If I attempt to use a URL ...

Manipulating cursor position in React's contentEditable

I created a simple component class ContentEditable extends React.Component { constructor(props) { super(props); this.handleInput = this.handleInput.bind(this); } handleInput(event) { let html = event.target.innerHTML; if (this.props. ...

The form within the dynamically loaded AJAX content is malfunctioning

My webpage is set up to load content from a separate file (content.php) into a div and refresh it every 5 seconds. In the content.php file, I have a form (basic HTML without javascript) that works fine when accessed directly at (example.com/content.php). ...

When using NextJS with Redux Persist, the HTML does not get rendered in the initial server

I am currently utilizing ReactJS/NextJS along with Redux and redux-persist, as well as Ant Design. Recently, I have noticed that my html codes and other data are not rendering in the page's source. They do render in the browser and when inspected, but ...

display different vue component based on screen size

I am in search of a method to implement responsive components in Vue.js (Nuxt). I have developed this mix-in but encountering an error: export const mediaQuery = { data() { return { breakpoints: { sm: 576, md: 768, lg: ...

Locate a specific element within a multi-dimensional array based on a partial match of one of its properties with a provided text

I am working with an array that includes three properties: ID : number Name : string Description :string ItemList :array<T>=[] and ItemListCopy :array<T>=[] Currently, this array is linked to the ng-multiselect dropdown During the onFilt ...

Tips on converting Django model into desired format for Bootstrap-tables plugin integration

I want to integrate the bootstrap-table plugin with server-side functionality using Django Rest Framework to populate the data on the table. However, I keep getting the message "No matching records found". After some investigation, I discovered that a spec ...

Leveraging Vuex in conjunction with dynamically generated components

I am exploring the idea of using Vuex to efficiently manage dynamically generated components in my application. Each page in the app consists of "field" components, with the ability for users to add multiple field components to each page. These field compo ...

React- Input value disappears after submission

Implementing validation for email-based input has been a bit of a challenge for me. I have managed to set up the debounce function for onChange event handling, but encountered a strange issue. The problem arises when the user submits an invalid string bef ...

Comparing Optimistic Updates and Tag Invalidation in RTK Query

I found a basic code example from the RTK query documentation: updatePost: build.mutation<void, Pick<Post, 'id'> & Partial<Post>>({ query: ({ id, ...patch }) => ({ url: `posts/${id}`, method: 'PUT', ...

Look for duplicate values in an array, retrieve the value, and determine the frequency

I've populated an array with a random number of strings. var array = ["car", "plane", "plane", "car", "car"]; I want to access the values in the Array and count how many times each one has been added. For example: var a = "car"; var aCount = 3; var ...

Mocking Async Await in Node.js Tests with JestJS

I'm currently trying to utilize Jest for testing my Node Js application (specifically AWS's Lambda), but I'm facing issues with mocking async await functionality. My setup involves babel-jest and jest-cli. Even though I reach the first cons ...

Instantly refreshing the Angular DOM following data modifications and retrieval from the database

I am currently working on a Single Page Application that uses Angular 8 for the frontend and Laravel for the backend. This application is a CRUD (Create, Read, Update, Delete) system. The delete functionality is working as expected, deleting users with spe ...

The function correctly identifies the image source without error

I possess a pair of images: <img id="img1" src="l1.jpg" usemap="#lb" height="400" border="0" width="300"> <img src="images.jpg" id="img2"> Next up is some JavaScript: function validateImages () { if (document.getElementById('img2&ap ...

Troubleshooting a 404 error for an existing object: What to do?

I encounter a 404 'Not Found' error when attempting to edit a mark through my form. I am puzzled by the source of this error because in order to access this form, I require the brand ID (which can be found in the URL). Upon accessing my modifica ...

Comparison: JavaScript Cookies vs PHP Cookies

I have been trying to implement the following code: JS: Cookies.set(post_id + '_' + user_ip, post_id + "_" + user_ip, { expires: 1 }); PHP: $cookie_str = $post_id.'_'.get_client_ip(); if (isset($_COOKIE[$cookie_str_]) ){ print_r ...

Unable to detect backspace events in an Ionic/Cordova application

In the process of developing my Ionic/Cordova app, I encountered a challenge with number input on Samsung devices. It seems that they do not display the decimal separator when the input type is set to number. If this were a native app, I could easily use t ...

Struggle with incorporating a file

As part of the login process, I have two options available: easy login and standard login. The easy login requires an employee ID, birthdate, and captcha answer, while the standard login asks for first name, last name, birthdate, and captcha. To facilitate ...

React Native automatically triggers the onPress event when using withNavigation

It seems that onPress should only be triggered by a touch event. Initially, this was the case, but when using withNavigation in a screen outside of the StackNavigator, onPress appears to render automatically. HomeScreen.js function mapStateToProps(state) ...