Prevent Sending Blank Forms with Stripe js

Currently, I am working on a solution to prevent users from submitting the stripe form when certain inputs are left empty. To achieve this, I have integrated stripe.js elements into my form and implemented the form submission handling within my vue component.

this.cardNumberElement.on('change', this.enableForm);
this.cardExpiryElement.on('change', this.enableForm);
this.cardCvcElement.on('change', this.enableForm);

Upon reviewing the documentation, I attempted to utilize the change event on inputs, but this approach proved ineffective as users could simply avoid typing anything and still click the submit button.

Below is a snippet of my vue component:

mounted()
{
    console.log(this.$options.name + ' component successfully mounted');

    this.stripe = Stripe(this.stripePK);
    this.elements = this.stripe.elements();

    this.cardNumberElement = this.elements.create('cardNumber', {style: this.stripeStyles});
    this.cardNumberElement.mount('#card-number-element');
    this.cardExpiryElement = this.elements.create('cardExpiry', {style: this.stripeStyles});
    this.cardExpiryElement.mount('#card-expiry-element');
    this.cardCvcElement = this.elements.create('cardCvc', {style: this.stripeStyles});
    this.cardCvcElement.mount('#card-cvc-element');

    let stripeElements = document.querySelectorAll("#card-number-element, #card-expiry-element, #card-cvc-element");
    stripeElements.forEach(el => el.addEventListener('change', this.printStripeFormErrors));
    this.cardNumberElement.on('change', this.enableForm);
    this.cardExpiryElement.on('change', this.enableForm);
    this.cardCvcElement.on('change', this.enableForm);
},

methods: 
{
    ...mapActions('Stripe', ['addSource', 'createSourceAndCustomer']),
    ...mapMutations('Stripe', ['TOGGLE_PAYMENT_FORM']),
    ...mapMutations('Loader', ['SET_LOADER', 'SET_LOADER_ID']),

    enableForm:function(event){
        if(event.complete){
            this.disabled = false;
        }
        else if(event.empty){
            this.disabled = true;
        }
    },


    submitStripeForm: function()
    {
        this.SET_LOADER({ status:1, message: 'Processing...' });
        var self = this;

        this.stripe.createSource(this.cardNumberElement).then(function(result) {
            if (result.error) {
                self.cardErrors = result.error.message;
            }
            else {
                self.stripeSourceHandler(result.source.id);
            }
        });   
    },


    stripeSourceHandler: function(sourceId)
    {
        console.log('stripeSourceHandler');

        this.cardNumberElement.clear();
        this.cardExpiryElement.clear();
        this.cvcElement.clear();

        if(this.customerSources.length == 0)
        {
            console.log('createSourceAndCustomer');
            this.createSourceAndCustomer({ id: sourceId });
        }
        else
        {
            console.log('addSource');
            this.addSource({ id: sourceId });
        }
    },


    printStripeFormErrors: function(event)
    {
        if(event.error)
        {
            self.cardErrors = event.error.message
        } 
        else
        {
            self.cardErrors = '';
        }
    }  
}

Answer №1

Based on the information provided in the stripe documentation, it appears that the use of the event is correct. However, there is room for improvement by including this.disabled = !event.complete to handle error cases as well as empty cases.

To ensure that the event is being triggered properly, you can try using console.log in the event callback function enableForm.

The issue may be related to the logic around disabling the submit button, which is not fully explained in your post. I have included a sample secure-component below that simulates triggering a change event when the value changes.

The key aspect lies within the container component:

  • The submit button is initially disabled using the data attribute disabled,
  • The submit button is enabled if the received event includes a property complete set to true. If false, it remains disabled.

I hope this information helps you pinpoint and address your issue effectively.

/**
Mock component to emulate stripes card element behavior with change event
*/
const SecureInput = {
  template: '<input type="text" v-model="cardnumber"/>',
  data: () => ({
    cardnumber: null
  }),
  watch: {
    cardnumber: function(val) {
      if(!val) {
        this.$emit('change', {empty: true, error: false, complete: false});
        return;
      }
      
      if(val.length < 5) {
        this.$emit('change', {empty: false, error: true, complete: false});
        return;
      }
      
       this.$emit('change', {empty: false, error: false, complete: true});
    }
  }
}

/* Logic is here */
const app = new Vue({
  el: '#app',
  components: {
    SecureInput
  },
  data: {
    disabled: true
  },
  methods: {
    updateDisable: function(event) {
      this.disabled = !event.complete;
    }
  }
 });
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <form @submit.prevent="$emit('submitted')">
    <p><secure-input @change="updateDisable"/></p>
    <p><input type="submit" :disabled="disabled"/></p>
  </form>
</div>

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

Which specific event in NextJS is triggered only during the initial load?

I am working on a NextJS app and I want to implement an initial loading screen that only appears during the first load. Currently, the loading screen pops up not only on the initial load but also whenever a link is clicked that directs the user back to the ...

What is the best way to restrict the degree of camera rotation in the left, right, up, and down directions in Three.js when using a

Although this question may have been asked before, I haven't been able to find a solution to my specific issue! I've set up a 3D canvas using WebGLRenderer, PerspectiveCamera, and OrbitControls. My camera's position is at 0, 10, 500 for the ...

Configuring Angular to use ES6 syntax

Trying to integrate angular google maps with es6 syntax has been a challenge for me. In es5, the code typically looks like this: .config(function(uiGmapGoogleMapApiProvider) { uiGmapGoogleMapApiProvider.configure({ // key: 'your api key&ap ...

Dynamic JavaScript tool

Does anyone know which library is being used on the website linked here? I am working on a project similar to this and would appreciate if anyone can identify this library for me. Thank you in advance. ...

The light slider feature is experiencing technical difficulties within the Bootstrap model

I am experiencing an issue with the Light Slider in a Bootstrap modal. Strangely, when I press F12 for inspect element, the Light Slider starts working. For more details and to see the link provided in the comment below, can anyone offer assistance, plea ...

Creating a Social Media Platform with JavaScript, Bootstrap, JQuery, PHP, and Mysqil

I am currently in the process of developing a social networking platform that will have similar features as Instagram. Users will be able to log in, create posts, leave comments, like content, share posts, and send data to a server for storage or display p ...

What is the process to enable a tab in AngularJS using Foundation's tab feature?

Currently, I am utilizing AngularJS in conjunction with Foundations. Visit the official website for more information Within my page, there are two tabs that are functioning correctly as shown below: <tabset> <tab heading="tab1"> </tab ...

Displaying a table in Chrome/Firefox with a mouseover feature

Hovering over the rows of this table triggers a display of descriptions. html: <tr title="{{transaction.submissionLog}}" class="mastertooltip">... JavaScript: $('.masterTooltip').hover(function(){ // Hover functionality ...

Development is hindered due to Cors policy restricting access to the localhost webapp

Currently, I am working on developing a web application and an API simultaneously, but I'm facing some issues with CORS blocking. This concept is relatively new to me, and I'm eager to improve my understanding. Firstly, I have set up an Express ...

Issue with vue-cli loader not functioning properly when utilizing default initialization for webpack-simple

Currently, I am in the process of learning Vue.JS. After installing the CLI and setting up a new project with the following commands: $ npm install -g vue-cli $ vue init webpack-simple vue-example $ cd vue-example $ npm install $ npm run dev # this is wh ...

jQuery smoothly sliding downward from the top to the bottom

http://jsfiddle.net/Hx65Q/3/ Is there a way to make the slider open from the top instead of the left side? $("button" ).click(function() { $('.login').toggle('slide', { duration: 1000, easing: 'easeOutBounce', }); ...

Adjust the text color based on the background image or color

Here on this site, I have designed the first div to display a dark image, while the second one shows a light background. I am aiming to adjust the sidebar text color based on whether it is displayed against the dark or light background. How can I achieve ...

Fix form errors in VueJs and submit for free!

I'm currently facing a challenge while developing a Vue form. I am struggling to submit the form without any error messages. Although I have successfully implemented error display, my goal is to redirect the page after pressing the submit button. If ...

How can you substitute sections of a sentence with an array of strings?

I have a specific sentence that needs formatting: span class="searchmatch" Program /span, programme, programmer, or span class="searchmatch" programming /span may refer to: span class="searchmatch" Program /span management, th ...

Seeking assistance with producing results

Is there someone who can provide an answer? What will be the output of the code snippet below when logged to the console and why? (function(){ var a = b = 3; })(); console.log("Is 'a' defined? " + (typeof a !== 'u ...

Node.js Express: Breaking Down Your Application into Modules

Currently, I am working on an express app and have the following code setup: MainApp.js const express = require('express'); const routes = require('./routes') const mainApp = express(); mainApp.listen(3000, () => { console.l ...

What is the best method for translating object key names into clearer and easier to understand labels?

My backend server is sending back data in this format: { firstName: "Joe", lastName: "Smith", phoneNum: "212-222-2222" } I'm looking to display this information in the frontend (using Angular 2+) with *ngFor, but I want to customize the key ...

Is a Page Refresh Required to Reload Routes in ReactJS?

I have created menu links labeled Home, About, What I Do, and Experience for my portfolio site using BrowserRouter. However, when I click on these links, the components do not load properly on the page; they only render correctly after a page refresh. This ...

What will occur if I use an XMLHttpRequest to request a file that is currently being downloaded?

My goal is to enhance links in a progressive manner using the PJAX style. My plan was to layer this on top of some regular prefetch <link>s: <link rel="prefetch" href="next.html"/> If the browser has already downloaded next.html, then the PJA ...

Converting the basic logic from if-else statements to foreach loops was unsuccessful

I am currently working with this function: const applyColor = (value) => { let color //shallow to dark const colors = ['#B3E5FC', '#81D4FA' ,'#4FC3F7', '#29B6F6', '#03A9F4', &ap ...