4

When the form_for() form is submitted using JQuery/AJAX/JS, the submit button fails to re-enable, even though I wrote code that switches the prop to disabled false.

I successfully activated the same JS line of code in the console, but it doesn't work when the validation for stripe fails normally.

var StripepayOnestepSubscriptionForm = {
   initialize: function () {
    $(document).off('submit.stripepay-onestep-subscription-form').on(
        'submit.stripepay-onestep-subscription-form', '.stripepay-onestep-subscription-form',
        function () {
            return StripepayOnestepSubscriptionForm.handleSubmit($(this));
        }
    );
},

handleSubmit: function (form) {
    if (!StripepayOnestepSubscriptionForm.validateForm(form)) {
        return false;
    }

    $(form).find('div :submit')
        .prop('disabled', true).change();
    $('.stripepay-spinner').css('visibility', 'visible');

    Stripe.card.createToken(form, function (status, response) {
        StripepayOnestepSubscriptionForm.stripeResponseHandler(form, status, response);
    });
    return false;
},

validateForm: function (form) {
    var cardNumber = $("input[data-stripe='number']").val();
    if (!Stripe.card.validateCardNumber(cardNumber)) {
        StripepayOnestepSubscriptionForm.showError(form, 'The card number is not a valid credit card number.');
        return false;
    }
    if ($("[data-stripe='exp']").length) {
        var valid = !Stripe.card.validateExpiry($("[data-stripe='exp']").val());
    } else {
        var expMonth = $("[data-stripe='exp_month']").val();
        var expYear = $("[data-stripe='exp_year']").val();
        var valid = !Stripe.card.validateExpiry(expMonth, expYear);
    }
    if (valid) {
        StripepayOnestepSubscriptionForm.showError(form, "Your card's expiration month/year is invalid.");
        return false
    }

    var cvc = $("input[data-stripe='cvc']").val();
    if (!Stripe.card.validateCVC(cvc)) {
        StripepayOnestepSubscriptionForm.showError(form, "Your card's security code is invalid.");
        return false;
    }

    return true;
},

stripeResponseHandler: function (form, status, response) {
    if (response.error) {
        StripepayOnestepSubscriptionForm.showError(form, response.error.message);
    } else {
        var email = form.find("[data-stripepay='email']").val();
        var coupon = form.find("[data-stripepay='coupon']").val();
        var quantity = form.find("[data-stripepay='quantity']").val();

        var base_path = form.data('stripepay-base-path');
        var plan_type = form.data('stripepay-plan-type');
        var plan_id = form.data('stripepay-plan-id');

        var action = $(form).attr('action');

        form.append($('<input type="hidden" name="plan_type">').val(plan_type));
        form.append($('<input type="hidden" name="plan_id">').val(plan_id));
        form.append($('<input type="hidden" name="stripeToken">').val(response.id));
        form.append($('<input type="hidden" name="stripeEmail">').val(email));
        form.append($('<input type="hidden" name="coupon">').val(coupon));
        form.append($('<input type="hidden" name="quantity">').val(quantity));
        form.append(StripepayOnestepSubscriptionForm.authenticityTokenInput());
        $.ajax({
            type: "POST",
            url: action,
            data: form.serialize(),
            success: function (data) {
                StripepayOnestepSubscriptionForm.poll(form, 60, data.guid, base_path);
            },
            error: function (data) {
                StripepayOnestepSubscriptionForm.showError(form, jQuery.parseJSON(data.responseText).error);
            }
        });

    }
},

poll: function (form, num_retries_left, guid, base_path) {
    if (num_retries_left === 0) {
        StripepayOnestepSubscriptionForm.showError(form, "This seems to be taking too long. Please contact support and give them transaction ID: " + guid);
    }
    var handler = function (data) {
        if (data.status === "active") {
            window.location = base_path + '/confirm_subscription/' + guid;
        } else {
            setTimeout(function () {
                StripepayOnestepSubscriptionForm.poll(form, num_retries_left - 1, guid, base_path);
            }, 500);
        }
    };
    var errorHandler = function (jqXHR) {
        StripepayOnestepSubscriptionForm.showError(form, jQuery.parseJSON(jqXHR.responseText).error);
    };

    if (typeof guid != 'undefined') {
        $.ajax({
            type: 'GET',
            dataType: 'json',
            url: base_path + '/subscription_status/' + guid,
            success: handler,
            error: errorHandler
        });
    }
},

showError: function (form, message) {
    $('.stripepay-spinner').css('visibility', 'hidden');
    $(form).find('div :submit')
        .prop('disabled', false).change()
        .trigger('error', message);

    var error_selector = form.data('stripepay-error-selector');
    if (error_selector) {
        $(error_selector).text(message);
        $(error_selector).show();
    } else {
        form.find('.stripepay-payment-error').text(message);
        form.find('.stripepay-payment-error').show();
    }
},

authenticityTokenInput: function () {
    return $('<input type="hidden" name="authenticity_token"></input>').val($('meta[name="csrf-token"]').attr("content"));
  }
};

StripepayOnestepSubscriptionForm.initialize();

The submit button remains disabled, after the error validation message is shown.

5
  • Have you checked that the showError function is definitely called? Does $(form).find('div :submit') in that function definitely return the expected DOM element? Commented Dec 24, 2018 at 9:31
  • The error messages are showing, but I can’t tell if the code for showError function is being reached. Since the code above it, is the error messages. How can I debug the method block for showError? Commented Dec 24, 2018 at 9:34
  • Put a console.log statement in the function and look for it in your browser console, or set a breakpoint in the function and see if it's hit, that kind of thing. Commented Dec 24, 2018 at 11:03
  • I added a console.log(“inside showError”) for showError method block. It does reach it. But, $(form).find(‘:submit’) doesn’t fire off. Do you think it’s due to it being wrapped in a div tag? Commented Dec 25, 2018 at 0:37
  • When I re-enable the prop in console. The button unlocks, but no longer submits Commented Dec 26, 2018 at 0:07

1 Answer 1

5
<%= f.submit “Sign up”, :class => ‘btn’, data: {disable_with: false} %> 

allowed the JS to control when the button changed states. (Rails 5) activates disable_with by default. Which was the cause of the error.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot! I wish had found your solution earlier. Just waisted a couple of hours on this... I just added a Ruby on Rails tag to your initial post, so hopefully other people can find your solution much faster.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.