How to prevent a user clicking the submit button twice
Some of our users are impatient an click twice (or more) on the submit button when submitting a node, which results in creating multiple identical nodes.
Do you have any ideas, how to prevent (e.g. disabling the submit button) while posting to the server?
@luxio This problem is becoming more common, and I'd like to build its solution directly into DG core.
In _drupalgap_form_submit(), if we do this after the form has been loaded:
https://github.com/signalpoint/DrupalGap/blob/7.x-1.x/src/includes/form.submission.inc.js
var submitButton = $('#' + form_id + ' button.dg_form_submit_button');
$(submitButton).prop('disabled', true);
That'll disable the button, then if the form fails to validate, we can re-enable it in _drupalgap_form_submit():
https://github.com/signalpoint/DrupalGap/blob/7.x-1.x/src/includes/form.submission.inc.js#L57
$(submitButton).prop('disabled', false);
Otherwise, I think we can just leave the submit button disabled forever, and let the developer re-enable it if they choose to, otherwise typically I recommend sticking a reloadPage option on any links to the form, that way next time the form is visited, it is loaded fresh.
Thoughts?
Thanks. Looks good.
I think the button should be also reenabled, if the service call returns an error (server down, network connection problem) so that the user can try to submit it again, without having entering the data again.
I think the button should be also reenabled, if the service call returns an error (server down, network connection problem) so that the user can try to submit it again, without having entering the data again.
Agreed. This will probably have to be on a per form basis, i.e. the user login form. We could let DG core automatically disable it, but then depending on what happens in the validation/submission handler of each form, they should be in charge of re-enabling it if necessary.
Where could I put in the node_edit form? In the error closure of the submission handler?
Need this as well
I am trying to hack the core for this.
Modified /src/includes/form.submission.inc.js
Executed make shows
Generating aggregated drupalgap.js file. done
Updated index.html from
<script type="text/javascript" charset="utf-8" src="bin/drupalgap-7.0.2.min.js"></script>
To
<script type="text/javascript" charset="utf-8" src="bin/drupalgap.js"></script>
But no luck, what am i missing ???
Note : No errors on make even if i mess with the src/* files
@devasghar Do you have npm installed? I'd recommend that instead, then you can just run grunt from the app's www directory, and it'll listen for changes to the src directory, and then autocompile the binaries for you. Either way though, the makefile should still work fine, I have it in case I'm developing on an environment that won't support npm.
@luxio This would probably be the best spot(s):
- https://github.com/signalpoint/DrupalGap/blob/7.x-1.x/src/modules/entity/entity.js#L606
- https://github.com/signalpoint/DrupalGap/blob/7.x-1.x/src/modules/entity/entity.js#L617
That way it'll cover it for all core entity types.
@signalpoint grunt worked fine,
I am sticking to the first solution for now, and its working https://github.com/signalpoint/DrupalGap/blob/7.x-1.x/src/includes/form.submission.inc.js
/**
* Handles a drupalgap form's submit button click.
* @param {String} form_id
* @return {*}
*/
function _drupalgap_form_submit(form_id) {
try {
// Load the form from local storage.
var form = drupalgap_form_local_storage_load(form_id);
+ // disabling the submit button to prevent multiple submission
+ var submitButton = $('#' + form_id + ' button.dg_form_submit_button');
+ $(submitButton).prop('disabled', true);
if (!form) {
var msg = '_drupalgap_form_submit - ' + t('failed to load form') + ': ' +
form_id;
drupalgap_alert(msg);
return false;
}
// Assemble the form state values.
var form_state = drupalgap_form_state_values_assemble(form);
// Clear out previous form errors.
drupalgap.form_errors = {};
// Build the form validation wrapper function.
var form_validation = function() {
try {
// Call the form's validate function(s), if any.
for (var index in form.validate) {
if (!form.validate.hasOwnProperty(index)) { continue; }
var function_name = form.validate[index];
var fn = window[function_name];
fn.apply(null, Array.prototype.slice.call([form, form_state]));
}
// Call drupalgap form's api validate.
_drupalgap_form_validate(form, form_state);
// If there were validation errors, show the form errors and stop the
// form submission. Otherwise submit the form.
if (!jQuery.isEmptyObject(drupalgap.form_errors)) {
var html = '';
for (var name in drupalgap.form_errors) {
if (!drupalgap.form_errors.hasOwnProperty(name)) { continue; }
var message = drupalgap.form_errors[name];
html += message + '\n\n';
}
+ //enabling the submit button again
+ $(submitButton).prop('disabled', false);
drupalgap_alert(html);
}
else { form_submission(); }
}
catch (error) {
console.log('_drupalgap_form_submit - form_validation - ' + error);
}
};
However the button is not being enabled on node_edit, node_add, comment_edit, comment_add errors like this one
POST localhost/site/?q=drupalgap/node.json 406 (Not Acceptable: An illegal choice has been detected. Please contact the site administrator.)
q=drupalgap/node.json 406 q=drupalgap/comment.json 406
Where to look ??
@devasghar Thank you for sharing the feedback, I'm glad we are on the right track. Please see the two links mentioned above as the spots to handle the submission of all entity forms.
Please review commit
This is working well so far
Note: button will still be disabled on javascript:drupalgap_back();
@devasghar see my comment.
I also like the idea of using the technique directly in _drupalgap_form_submit(), that way ever single form will have this behavior, not just entity forms. We can use the entity form submission handlers to re-enable the button if there was a problem. Other forms may need to take special action to re-enable the button, e.g. user login form when an incorrect password is entered. We're on the right track here though, thank you.
Ok now we have this on both _drupalgap_form_submit() & entity level & is working so far, but we need to handle the 401 now
POST localhost/site/?q=drupalgap/user/login.json 401 (Unauthorized: Wrong username or password.) POST localhost/site/?q=drupalgap/node.json 401 (Unauthorized: Access denied for user anonymous)
@signalpoint
@luxio This would probably be the best spot(s):
https://github.com/signalpoint/DrupalGap/blob/7.x-1.x/src/modules/entity/entity.js#L606 https://github.com/signalpoint/DrupalGap/blob/7.x-1.x/src/modules/entity/entity.js#L617 That way it'll cover it for all core entity types.
Thanks, works great. I am also disabling the the submit button in drupalgap_entity_form_submit(), in order to prevent having the submit button still being disabled in other forms (e.g. user login) in case of an error.