submit form with ajax validation jquery / standard javascript - javascript

I'll start with an apology - I'm a .NET coder with little (no) front-end experience.
When the user clicks on Submit, the form needs to call a REST service, if the service returns true then the user is presented with a warning that a duplicate exists and are asked whether they want to continue. Appreciate any help.
I have the Submit button ONCLICK wired up to Approve()
When the checkForDuplicateInvoice() gets called, it passes the control back to the calling function right away before the ajax call has a chance to get the result. The effect is that the Validate() function finishes without taking into account whether or not a duplicate invoice exists.
I need help in modifying the form so that when the user clicks on the submit button, the form validates (including the ajax call to the db) before finally submitting.
I've modified the code based on Jasen's feedback.
I'm including https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js in my header.
The error I get now is "Object doesn't support property or method 'button'"
What I have now for my form submission/validation is:
$(document).ready(function () {
$("#process").button().click( function () {
if (ValidateFields()) { // internal validation
var companyCode = document.getElementById("_1_1_21_1").value;
var invoiceNo = document.getElementById("_1_1_25_1").value;
var vendorNo = document.getElementById("_1_1_24_1").value;
if (vendorNo == "undefined" || invoiceNo == "undefined" || companyCode == "undefined") {
return false;
}
$.ajax({ // external validation
type: "GET",
contentType: "application/json;charset=utf-8",
//context: $form,
async: false,
dataType: "jsonp",
crossDomain: true,
cache: true,
url: "http://cdmstage.domain.com/services/rest/restservice.svc/CheckDuplicateInvoice?InvoiceNumber=" + invoiceNo + "&VendorNumber=" + vendorNo + "&CompanyCode=" + companyCode,
success: function (data) {
var result = data;
var exists = result.CheckForInvoiceDuplicateResult.InvoiceExists;
var valid = false;
if (exists) {
if (confirm('Duplicate Invoice Found! Click OK to override or Cancel to return to the form.')) {
valid = true;
}
}
else {
valid = true; // no duplicate found - form is valid
}
if (valid) {
document.getElementById("_1_1_20_1").value = "Approve";
doFormSubmit(document.myForm);
}
},
error: function (xhr) {
alert(xhr.responseText);
}
});
}
});
});

First review How do I return the response from an asynchronous call? Understand why you can't return a value from the ajax callback functions.
Next, disassociate the submit button from the form to prevent it from performing default submission. Test it to see it does nothing.
<form>
...
<button type="button" id="process" />
</form>
Then wire it up to make your validation request
$("#process").on("click", function() {
if (valid()) {
$(this).prop("disabled", true); // disable the button to prevent extra user clicks
// make ajax server-side validation request
}
});
Then you can make your AJAX request truly asynchronous.
$.ajax({
async: true,
...,
success: function(result) {
if (exists) {
// return true; // returning a value is futile
// make ajax AddInvoice call
}
}
});
Pseudo-code for this process
if (client-side is valid) {
server-side validation: {
on response: if (server-side is valid) {
AddInvoice: {
on response: if (successful) {
form.submit()
}
}
}
}
}
In the callback for the server-side validation you make the AddInvoice request.
In the callback for AddInvoice you call your form.submit().
In this way you nest ajax calls and wait for each response. If any fail, make the appropriate UI prompt and re-enable the button. Otherwise, you don't automatically submit the form until both ajax calls succeed and you call submit() programmatically.

Related

How to hook into woocommerce_after_checkout_validation depending on the AJAX JSON results

I added a custom input to the WooCommerce checkout form and it receives a JSON data from an URL. If the user's input, was valid, the received JSON will will have a true value, if not, it will have a false value in it.
I already did that using the AJAX JQuery function.
What I want?
When user clicks on the Place order button, besides other potential errors, I want to add a validation error to the WooCommerce if the received JSON data is false. If the user corrected the input and received true value from URL, when clicking on the Checkout button again, I want the error to be cleared.
How can I hook into woocommerce_after_checkout_validation and add/remove validation errors on the fly with JS/JQuery? I added some comments to the code to make my problem a bit clearer.
//custom-wc-checkout.js
$(document).on("input", "#custom_input", function () {
console.log($(this).val());
var value = $(this).val();
var isValidCode = false;
function checkCode(value, callback) {
$.getJSON(
"http://localhost/special/wp-json/wp/v2/posts/" + value,
function (jsonData) {
isValidCode = jsonData.content.protected;
callback(isValidCode2);
}
);
}
checkCode(value, function (isValidCode) {
// Is it true or false
console.log(isValidCode);
$.ajax({
url: "http://localhost/special/wp-admin/admin-ajax.php",
async: false,
type: "POST",
data: {
action: "validate_e_code",
json: isValidCode,
},
dataType: "text",
success: function (response) {
console.log("success");
console.log(response);
json = data.json;
},
error: function () {
console.log("error");
},
});
});
});
PHP code:
//Ajax.php
$isValid = false;
function validate_e_code()
{
global $isValid;
$isValid = $_POST["json"];
//Update: I tried to add a custom session as CBroe advised,
//but I don't know how to use the session to tell the WooCommerce
//update the validation results depending on the session value.
WC()->session->set('the_field_name', $isValid);
echo json_encode(WC()->session->get('the_field_name'));
echo $isValid;
die();
}
//$isValid remains false, even if the input code is valid and $_POST["json"]'s value is true
//So it always displays the error
if ($isValid == false) {
add_action('woocommerce_after_checkout_validation', 'validate_json', 10, 2);
}
function validate_json($fields, $errors)
{
$errors->add('validation', 'Your code is not valid!');
}
PS I used the WordPress REST API for testing. It doesn't matter, only note that the JS code returns a true or false value, depending on what user enters in #custom_input (custom field) and then we pass the Boolean value to the validate_e_code PHP function.

Can I return multiple values to the Onclick event of a Hyperlink?

I have a delete link for every row in my grid. It looks like this:
<font color="#CC0000">Delete</font>
My objective is to check if a record has been printed or not by making an Ajax call to an ASP.net Web Method two times. Once before the user confirms delete, and once again after they click confirm.
I easily took care of this by creating a synchronous AJAX call, but I read everywhere that synchronous AJAX calls are horrible and depricated.
After looking here I decided to use JQuery deferred objects to grab the response values
What I did was this:
After clicking "Delete" OnDeleteRecordClick(recordID) gets called.
First, I make my Ajax Call, then return false (notice the end of the method)
Then, after I get the first response, depending on if the record is not printed or not, I show a javascript confirmation, and make my ajax call again, Then return false again.
After the second response, if the record is unprinted, I return true, to delete the record.
Here's my OnDeleteRecord:
function OnDeleteRecordClick(recordID) {
// This action takes place asynchronously
BeforeRecordDelete (recordID)
.done(function (r) {
if (r.d == 1) {
// Check isPrinted before clicking "Confirm"
alert("You can't delete this record printed.");
return false;
} else {
if (ConfirmDelete('record')) {
// Check isPrinted again after clicking "Confirm"
BeforeRecordDelete (recordID)
.done(function (r) {
if (r.d == 1) {
alert("You can't delete this record because it has been printed.");
return false;
} else {
// Proceed to delete
return true;
}
})
.fail(function (x) {
Alert("server failed");
return false
});
// Return false until we get a response from the server
return false;
} else {
// User clicks "Cancel"
return true;
}
}
})
.fail(function (x) {
// Tell the user something bad happened
Alert("server failed");
return false;
});
// Return false until we get a response from the server
return false;
}
Here's my async AJAX call:
BeforeRecordDelete = function (recordID) {
return $.ajax({
type: "POST",
url: "RecordList.aspx/IsRecordPrinted",
contentType: "application/json; charset=utf-8",
data: '{RecordID: "' + RecordID + '"}',
dataType: "json"
});
}
Here's my problem: When I return false two times, then return true, the hyperlink wouldn't work.
My questions are:
Can I even do this to a hyperlink? (Returning multiple values to OnClick)
Is there a better way to do this? I really want to do this asynchronously, but my brain hurts.

Prevent submit on a jQuery form

I'm setting up a password control on a login form with jQuery and ajax.
So far, this is the script
$(document).ready(function() {
$("#login-form").submit(function(e) {
var csrftoken = getCookie('csrftoken');
var password = $('#login-password').val();
var email = $('#login-email').val();
$.ajax({
url: "/password_check/",
type: "POST",
dataType: "json",
data : {
csrfmiddlewaretoken: csrftoken,
password: password,
email: email
},
success: function(result) {
document.getElementById("login-error").innerHTML = result.response;
event.preventDefault();
}
});
return false;
});
});
With this, the error gets caught when firing the submit button, but if the password is correct the submit doesn't work (even though the error doesn't show up anymore).
What am I missing?
You have an asynchronous ajax call, so by the time your success function fires, the form submit event has passed so you need to submit the form again but use the DOM method, which will bypass the jQuery event handler and allow the form to submit.
success: function(result) {
if(result == "correct"){
document.getElementById("login-form").submit();
} else {
document.getElementById("login-error").innerHTML = result.response;
}
}
As you didnt say what response indicates a correct password, I have used result == "correct", so change that accordingly.
You have to return false only if u dont want to submit the form.
If password is correct you need to return true in your case.

How do I submit a form using jQuery after AJAX validation?

My form has one input which needs to be validated before submitting. After a successful validation I try to submit the form, but it doesn't submit.
My code looks like this:
$(document).ready(function() {
$("#myForm").submit(function () {
checkInputData();
return false; // to prevent default submit
});
});
The validation function:
function checkInputData() {
var id = $($("#id")).val(); // value, which needs to be validated
$.get("check.php?id=" + id,
function(result){
if(result == 1) {
//if the result is 1, need to submit
$("#myForm").unbind(); // to prevent recursion?
$("#myForm").submit(); // doesnt work
} else {
// dont submit, give some visual feedback, etc...
}
});
}
What am i doing wrong? Thanks.
You need to return the result from your AJAX validation request. You can do this by setting this check to being async: false, this means the checkInputData() will wait for the result to come back, and you can return it, controlling the submission of the form.
In your code it's not waiting for the $.get action to happen, and it appears to skip over meaning your code will always appear to return true; from the checkInputData() call. You don't need to return false in submit, if used as below.
I have used the $.ajax call in place of $.get because it allows you to control the async property, but it essentially does the same thing. You can read more about it here.
function checkInputData() {
var value = $("#id").val(); // Value to be validated
var passedValidation = false;
$.ajax("check.php?id=" + value, {
async: false,
success: function(result){
// Do whatever check of the server data you need here.
if(result == "1") {
// Good result, allow the submission
passedValidation = true;
} else {
// Show an error message
}
}
});
return passedValidation;
}
$(document).ready(function() {
$("#myForm").on("submit", function () {
return checkInputData();
});
});
I assume you have a button such as below, within your form with id myForm:
<input type="submit" value="Submit Form" />
It's not getting submitted may be because you are not returning 1 on successful validation for result in below if condition
if(result == 1) {
In check.php your output should be 1, like echo '1'; if input is valid. And make sure there is not any other output before or after it.
AMember is correct your always returning false, there are a few solution. One solution is for you to bind your validation to a button element or any element that will not submit the form.
HTML
<form id="myForm">
.
input elements
.
<button class= "submit" type="button" onclick="submit">Submit</button>
</form>
Document Ready
$(function()
{
var $submit = $(".submit");
$submit.click(function ()
{
checkInputData();
});
});
Validation Callback Function
function checkInputData()
{
var id = $('#id').val(); // value, which needs to be validated
$.get("check.php?id=" + id, function(result)
{
if(result == 1)
{
var $myForm = $("#myForm");
//if the result is 1 submit.
$myForm.submit();
}
else
{
// dont submit, give some visual feedback, etc...
}
});
}
$(document).ready(function() {
$("#myForm").submit(function (e) {
checkInputData();
//return false; // to prevent default submit <-- THIS IS WRONG
e.preventDefault(); //Try this :)
});
});
Returning false will prevent it from submitting in all cases.

Given a form submit, how to only submit if the server first responses back with a valid flag?

I have a form, with a text input and a submit button.
On submit, I want to hit the server first to see if the input is valid, then based on the response either show an error message or if valid, continue with the form submit.
Here is what I have:
$('#new_user').submit(function(e) {
$.ajax({
type: "POST",
dataType: 'json',
url: "/users/stuff",
data: $('#new_user').serialize(),
success: function(data){
if (data.valid) {
return true
} else {
// Show error message
return false;
e.preventDefault();
}
}
});
});
Problem is the form is always submitting, given the use case, what's the right way to implement? Thanks
Try like this:
$('#new_user').submit(function(e) {
var $form = $(this);
// we send an AJAX request to verify something
$.ajax({
type: "POST",
dataType: 'json',
url: "/users/stuff",
data: $form.serialize(),
success: function(data){
if (data.valid) {
// if the server said OK we trigger the form submission
// note that this will no longer call the .submit handler
// and cause infinite recursion
$form[0].submit();
} else {
// Show error message
alert('oops an error');
}
}
});
// we always cancel the submission of the form
return false;
});
Since you're already submitting via AJAX why not just submit the data then if it's valid rather than transmit the data twice?
That said, the function that makes the Ajax call needs to be the one that returns false. Then the successvfunction should end with:
$('#new_user').submit()
The fact that AJAX is asynchronous is what's throwing you off.
Please forgive any typos, I'm doing this on my cell phone.
Submitting the same post to the server twice seems quite unnecessary. I'm guessing you just want to stay on the same page if the form doesn't (or can't) be submitted successfully. If I understand your intention correctly, just do a redirect from your success handler:
$('#new_user').submit(function(e) {
$.ajax({
type: "POST",
dataType: 'json',
url: "/users/stuff",
data: $('#new_user').serialize(),
success: function(data){
location.href = "success.htm";
},
// if not valid, return an error status code from the server
error: function () {
// display error/validation messaging
}
});
return false;
});
Another approach
EDIT: seems redundant submitting same data twice, not sure if this is what is intended. If server gets valid data on first attempt no point in resending
var isValid=false;
$('#new_user').submit(function(e) {
var $form = $(this);
/* only do ajax when isValid is false*/
if ( !isValid){
$.ajax({
type: "POST",
dataType: 'json',
url: "/users/stuff",
data: $form.serialize(),
success: function(data){
if (data.valid) {
isValid=true;
/* submit again, will bypass ajax since flag is true*/
$form.submit();
} else {
// Show error message
alert('oops an error');
}
}
});
}
/* will return false until ajax changes this flag*/
return isValid;
});

Categories

Resources