简体   繁体   中英

Seeking more elegant solution to preventDefault() dilemma

I have a jQuery form-submission routine that has an input integrity check in ERROR_CHECK.PHP that relies on GET variables passed to it for inspection. If the values passed to it are malformed, then an alert box appears that explains the error and how the form data should be remedied. This alert box will need to pop up until the form data is no longer malformed, at which point that data is used for repopulating data on the page.

Thus, in the jQuery routine I'm at the mercy of our friend preventDefault() , and I have found a solution that does work, but not elegantly. The variable allowSubmit is initialized as FALSE and remains that way—with preventDefault() also in effect—until the form data passes the integrity check, at which point allowSubmit switches to TRUE ...but that only happens with the submission of the correctly-formed input data. This means the user must submit the form a SECOND TIME in order for the form data to be used to replace data on the page...and that, of course, is not a solution (press the submit button twice?)

However, by dynamically submitting the form (here, with the $('#my_form').submit() statement) immediately after resetting allowSubmit to TRUE , I've submitted the form again, thereby allowing the user to submit correctly-formatted data ONCE, as it should be from the get-go.

This is obviously a band-aid solution and not elegant. Can anyone see a more elegant way to structure this? (I'm working with jQuery fashioned by another developer, and this occurs in the midst of a longer self-calling JQuery function, and I have to work with it on its own terms, lest I have to refashion all other parts of the larger function in which it occurs.

Here's a distillation of the code (with self-describing variables, etc.), which works as described, although not as elegantly as I'd like:

var allowSubmit = false;
$('#my_form').on('submit', function(e) {
    if (!allowSubmit) { 
        e.preventDefault();
        // Check to see if input data is malformed:
        $.get('error_check.php', { new_element_name: $('#new_element_name').val() }, function(data) {
            if (data != 0) {
                alert("An Error Message that explains what's wrong with the form data");
            } else {
                allowSubmit = true;
                // The line below--an auto-submit--is needed so we don't have to press the submit button TWICE.
                // The variable allowSubmit is set to TRUE whenever the submitted form data is good, 
                // but the code suppressed by e.preventDefault() won't execute until the form is
                // submitted a second time...hence the need for this programmatic form submission here.
                // This allows the user to correct the errant form data, press the submit button ONCE and continue.
                $('#my_form').submit();
            }
        });
    }
    $('#element_name').val($('#new_element_name').val());
});

What you are doing is okay, your other options might be to write a click handler for a generic button and submit the form through that event after validation, then you wont need to preventDefault as you won't be preventing any kind of submit action. Another solution might be to re-trigger the event after validation.

           $("button").click(function() {
               $("#my_form").submit();
           });
           ...
                allowSubmit = true;
                // alternatively
                jQuery( "body" ).trigger( e );
           ...

You could try using an async: false setting using $.ajax (I don't know what your php is returning, so I am just "pretending" it's a json array/string like so echo json_encode(array("response"=>$trueorfalse)); ):

<script>
$('#my_form').on('submit', function(e) {
        var valid_is    =   true;
        // Check to see if input data is malformed:
        $.ajax({
                async: false,
                url: 'error_check.php',
                type: 'get',
                data: { new_element_name: $('#new_element_name').val() },
                success: function(response) {
                    var Valid   =   JSON.parse(response);
                    if(Valid.response != true) {
                            alert("An Error Message that explains what's wrong with the form data");
                            valid_is    =   false;
                        }
                }
        });

        if(!valid_is)
            e.preventDefault();

    $('#element_name').val($('#new_element_name').val());
});
</script>

If you use async: false it runs the script in order and waits to execute the rest of the script until after it receives a response. Scott G. says you can do it with what you have with some slight modifications so I would try that first.

The callback solution you have doesn't seem unreasonable. I agree with @scott-g that a generic button click event handler would probably be your best bet. A more testable way to write what you have here may be:

var formView = {
  $el: $('#my_form'),
  $field: $('#element_name'),
  $newField: $('#new_element_name'),
  $submitBtn: $('#btn-submit')
}

var handleSubmit = function() {
  var formData = formView.$field.val();
  remoteVerify(formData)
    .done(formView.$el.submit)
    .done(updateForm)
    .fail(handleVerificationError);
};

var remoteVerify = function(formData) {
  var deferred = $.Deferred();
  var url = 'error_check.php';
  var data = { new_element_name: formData };
  $.get(url, data)
    .done(handleRequest(deferred))
    .fail(handleRequestErr);
  return deferred;
};

var handleRequest = function(deferred) {
  return function (data, jqxhr) {
    if (data != 0) {
      deferred.reject(jqxhr, "An Error Message that explains what's wrong with the form data");
    } else {
      deferred.resolve(data);
    }
  }
};

var handleRequestErr = function() {
  // error handling
}

var updateForm = function () {
  formView.$field.val(formView.$newField.val());
}

var handleVerificationError = function (jqxhr, errMsg){
  alert(errMsg); 
}

formView.$submitBtn.on('click', handleSubmit)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM