0

I have a simple acceptance form that has a single button that the user clicks. On form submit, I have a php script that makes a command line call to a python script that adds records to my database. All works great besides one thing: I don't want the user to be able to click the button more than once.

  • If I disable the button using javascript, my if (isset($_POST['submit'])) statement doesn't evaluate to true and then my php doesn't run
  • If I call a javascript function within the php script, the user still has an opportunity to click the button multiple times before the php script calls the function to disable the button. This allows them to make multiple records in my db.

My idea was to have my python script, which is the one adding records, first check if a record with the same information already exists in the db and only create a new one if not. My concern is that if the user clicks the submit button multiple times, it could be that multiple php will execute multiple calls and the second one will check if a record is already created before the first call creates a new record.
In other words, maybe the php calls will work at the same time (asyncronously?) and checking the database won't cover for another call creating a record at the same time. Is this a valid concern?

Are there other ideas of how I could disable or hide my button but still have my php script run? Thank you.


For future viewers, the workaround I ended up using is based on what Teemu said in the comments below. Before adding a new record from the form submission to the db, I checked if a record already existed with that information. If not, I added a record, if so the button click did nothing. As Teemu mentioned, this check would be necessary anyway to cover for multiple submissions that could be posted even without the button on the page. This is what I call a "workaround" and not an answer because the user can still click the submit button multiple times but only the first click has an effect. The button then hides itself after the php has finished running.

sFishman
  • 137
  • 9
  • I don't know why you can save the values using php instead of python and you are trying to glue that together.... use the KISS method. – Vidal Apr 21 '20 at 11:44
  • Either way, my problem would still remain. Even if I interact with the db using php, I still need the button to be disabled right away so the user can't send multiple php calls. – sFishman Apr 21 '20 at 11:48
  • 1
    You've to check the count of the submissions on the server anyway, even if you'd drop the submit button entirely, a user is still capable to post the form. – Teemu Apr 21 '20 at 11:49
  • not really, because you can send the form to another page for "processing" the data save it into the database and redirect the user to another page. By doing this there's no possibility that the user push the button twice and add 2 records. – Vidal Apr 21 '20 at 11:51
  • @Vidal What if the user clicks Back button? Or "the user" is a server, which doesn't even need OP's form or the page. – Teemu Apr 21 '20 at 11:54
  • @Teemu How do you check the number of submissions to the server? Using php? – sFishman Apr 21 '20 at 11:58
  • That depends ... If the user is a logged-in user, you can store the count in a session variable, check the data already exists. In all cases, when you want the data being stored only once, you've to make a final check at your server. You can disable, or even omit the submit button, but that really doesn't prevent users to resubmit. At simplest, they open the Network tab of the DevTools, and modify the previously submitted data and resend the form, even if there wasn't the submit button or even the form available. – Teemu Apr 21 '20 at 12:02
  • So is it enough if before I create a new record to check that that record doesn't already exist in the db? Do I have to be worried about multiple requests being sent around the same time and then this uniqueness check not working? – sFishman Apr 21 '20 at 12:05
  • 1
    Usually database handles the simultaneous actions, and a check should still work. – Teemu Apr 21 '20 at 12:09

2 Answers2

2

All you need is that the disabled is set after the submission is sent. You can achieve that using a setTimeout with zero delay:

$('.myForm').submit(function () {
  setTimeout(() => {
    $(this).find('[type=submit]').prop('disabled', true)
  }, 0)
})

Then, the following will happen:

  • Form submission event is fired because user clicked the button or pressed Enter
  • Browser is calling your submit handler
  • You are "arming" your timeout
  • Browser is submitting the form to the server (with the submit button's value)
  • Your timeout fires immediately afterwards, disabling the button

Note that I used a submit handler on the form instead of a click handler on the button because the form may be submitted by pressing Enter while focus is on a form field too, not only by clicking the button. Yet due to how form submission works, disabling the button will also prevent submission by Enter.

CherryDT
  • 25,571
  • 5
  • 49
  • 74
  • Disabling the button after or within my php that occurs on submit does the same thing as this. This doesn't solve the problem because while the php is running, there is delay during which the user can click the button multiple times. Then the form/button is only disabled AFTERWARDS. The double-clicking has already been done. – sFishman Apr 23 '20 at 08:04
  • I don't understand what you mean. This is JavaScript, not PHP. It runs in the browser, approx. one millisecond after the button is clicked, before the browser even sent the request to your server or any PHP ran. – CherryDT Apr 23 '20 at 13:42
  • I misunderstood what this was doing. This worked nicely. Thank you. – sFishman Apr 27 '20 at 07:42
0

I recently had a similar situation where I was getting a double-click 'bounce' sometimes. Here's two ways I dealt with it:

1) Simply disable the button, send the AJAX data to PHP and restore the button on success

$("#save_button").click(function (e) {
            e.preventDefault();
            $(this).attr("disabled", true);
            var settings = $('form').serialize();
            console.log("settings are ", settings);
            $.post("data/ajax.php", settings, function (data) {
                data = JSON.parse(data);
                console.log("data back from save is ", data);
                $("#save_button").removeAttr("disabled");
            })
        });

2) create a 'nobounce' function (it does basically the same thing, but on a timer. It is a bit simpler to use as it only requires setting the class 'nobounce' on any button you want to disable, though as it is on a timer, it isn't as accurate to enable the button when the post is done.

    $('.nobounce').click(function () {
        $(this).attr("disabled", true);
        setTimeout(function () {
            $('.nobounce').removeAttr("disabled");
        }, 3000);
    });

These are both jquery methods - keeping the form on the page. From your description it seems maybe you are doing a form submit through PHP (please, if this isn't the answer you need, put up some code you are using so this can be more clear!). If you are submitting through PHP, then some of the comments to the original question are extremely valid.

Hope this helps - again, if not, put up some code and you can get much more direct help.

Apps-n-Add-Ons
  • 2,026
  • 1
  • 17
  • 28