I've spent some time looking around and trying multiple solutions without luck, while attempting to streamline a form to create a pseudo bulk process.
Essentially I simply need to prevent default on a submit button, but to trigger it if several subconditions are met, at least one of which uses an ajax call.
I've tried variations of e.preventDefault, $('#form').submit(false); and I can either get the validation to occur, or the form to submit, but never both in the right places. (for example it will submit without checking for duplicate entries)
Here's a summed up version of what I've been attempting.
This is the main variable which holds the first part of the check:
var verifyValue = function() {
// this stops the form, and then things validate fine.
$('#add-item-form').submit(false);
//but then I need to get it started again to submit valid entries
if($('#value_of_json_array').val().length != 0){
$('#value_of_json_array').prop("readonly", true);
jQuery.getJSON('{{ path('query_to_get_array') }}?' +
$.param({barcode: $('#value_of_json_array').val()}))
.done(checkedValue);
}
};
This is where it is called:
$("#verify-value").click(verifyValue);
Below is a shorthand of the conditional being run:
var checkedValue = function(items) {
if(items.length == 0){
// success conditions
}
else {
//this was just one attempt
$('#form').submit(false);
if( /* sub condition of data passed from JSON array */){
//condition creates new form which upon action sends AJAX call
}
else
{
//second error condition
}
}
};
What I'm trying to do is to have if any of the subconditions occur, to have it stop the submit button (e.g. preventDefault behavior) and if it does not have any of these, to allow the submission of the form
It feels like it should be simple, however no matter where I do this, including using $(this).unbind('submit').submit() It doesn't work right.
Either the validation occurs correctly and nothing submits, or everything submits even if it's not supposed to.
I feel like modifying var verifyValue will work but I'm not sure how to get the conditional statements bound into an event.
Edit:
Okay, so I was guilty of seriously overthinking this issue, and came up with a solution which I will put below (in case anyone is interested)
Since your validation includes an async step, it'd be easier to just stop the form submission right away.
Then call your validation function, which will set the validation state of the form in a "global" state (maybe just a closure of the event handler). If the validation is fine, submit the form, else just show the validation error.
// You'll need to reset this if an input changes
var isFormValid = false;
$("#form").on('submit', function(e) {
if (isFormValid) {
return true;
}
e.preventDefault();
validateForm(function(valid) {
if (valid) {
isFormValid = true;
$('#form').submit();
}
});
});
function validateForm(cb) {
var form = $('#form');
// do some synchronous validations on the form inputs.
// then do the async validation
if($('#value_of_json_array').val().length != 0){
$('#value_of_json_array').prop("readonly", true);
jQuery
.getJSON(
'{{ path('query_to_get_array') }}?' +
$.param({barcode: $('#value_of_json_array').val()})
)
.done(function(result) {
if (checkedValue(result)) {
cb(true);
} else {
cb(false);
}
});
} else {
cb(false);
}
}
How about this approach, here's a simple skeleton:
$('#form').submit(function(e){
var formError = false;
// set formError to true if any of the checks are not met.
if(some condition) {
// do a conditional check
formError = true;
} else if(another condition) {
// do another conditional check
formError = true;
}
if(formError) { // stop form submission of any of the conditions are not met.
return false; // same as e.preventDefault and e.stopPropagate()
}
});
It turned out I was seriously overthinking this issue. It was a lot easier to handle by binding everything into a button that was not a submit, and if it passed the validation simply use a submit condition. This way I didn't need to worry about preventing default behavior and turning it back on again (which was where I was getting stuck). Since regular buttons have no default behavior, there was no need to be concerned about it submitting incorrectly.
The original function just needed to be simplified to:
var verifyValue = function() {
if($('#value_of_json_array').val().length != 0){
$('#value_of_json_array').prop("readonly", true);
$('#barcode-buttons').hide();
jQuery.getJSON('{{ path('query_to_get_array') }}?' +
$.param({barcode: $('#value_of_json_array').val()}))
.done(checkedValue);
}
};
$("#verify-value").click(verifyValue);
and then the check only needed to do this
var checkedValue = function(items) {
if(items.length == 0){
$('#form').submit()
}
else {
//error conditions
}
};
Related
I have some very old javascript code on an existing site and I wanted to update it, but I'm running into errors and I'm not sure what to replace it with. The code is just part of a section where it does a .submit() call to the form. Then the code reaches the try condition, it throws the error that livequery is not a function. Code is also below the screenshot.
Also I'm not sure if the "var form" is outside the scope of the try for form to work or not. What could I have wrong here?
var submit = false;
var form = $("#webform-client-form-2")[0];
try {
if (repair) {
console.log('repair is true - line 317');
$(".simple-dialog").click();
$(".ui-dialog, .ui-widget-overlay").hide();
$(".form-actions").livequery(function() {
console.log('livequery - line 321');
$("#edit-submitted-name").val(subject_field);
$("#edit-submitted-phone").val(phone);
$("#edit-submitted-email").val(email);
$("#edit-submitted-details-of-issue").val(problem);
var find = $(".form-actions")[0]; //get the 1st form actions on the page. if more than 2 forms on page, this might submit wrong form.
if (!submit && find) {
console.log('repair is true - line 328');
submit = true;
$("#webform-client-form-2").submit();
$(".form-actions").expire();
return false;
}
});
} else if (contact) {
console.log('yyy');
console.log(form);
$("#edit-submitted-phone-number").val(phone);
$("#edit-submitted-message").val(problem);
$(form).submit();
} else {
console.log('zzz');
$(form).submit();
}
} catch (error) {
console.log(error);
console.log("no form - line 346");
}
I'm building a registration page and I want the button to be disabled until all of the inputs pass validation. Well I have all of the native validation logic done (missing values, pattern mismatch, etc...), but I wanted to implement a "username taken/available" piece of validation where the button still wouldn't be enabled until the username had valid inputs for all of their inputs AND supplied a desired username that was not already in use.
I have the server call and all of that all done, my only issue is the actual enabling/disabling of the button and assigning the border classes to the inputs. Here is my code for the response from the AJAX call:
ajax.onload = function() {
if (this.responseText === "taken") {
if (username.classList.contains("taken")) {
return;
} else {
username.classList.remove("successBorder");
username.classList.add("errorBorder");
username.classList.add("taken");
}
} else {
if (!username.checkValidity()) {
username.classList.remove("successBorder");
username.classList.add("errorBorder");
return;
} else {
username.classList.remove("errorBorder");
username.classList.add("successBorder");
username.classList.remove("taken");
}
}
}
And then here is the code for where the button is enabled/disabled that is called on the input event for every input element:
function validate() {
if (document.querySelector("form").checkValidity() && !(username.classList.contains("taken"))) {
registerButton.removeAttribute("disabled");
const ruleSpans = document.querySelectorAll("span[data-rule]");
for (span of ruleSpans) {
span.classList.add("hide");
}
for (input of inputs) {
input.classList.remove("errorBorder");
input.classList.add("successBorder");
}
return;
}
registerButton.setAttribute("disabled", "true");
if (this.checkValidity()) {
// Get rid of the error messages
this.classList.remove("errorBorder");
this.classList.add("successBorder");
const ruleSpans = document.getElementsByClassName(this.id);
for (span of ruleSpans) {
span.classList.add("hide");
}
return;
}
// Adding attention borders and error messages based upon what the issue is
this.classList.remove("successBorder");
this.classList.add("errorBorder");
const ruleSpans = document.getElementsByClassName(this.id);
for (span of ruleSpans) {
span.classList.add("hide");
switch (span.getAttribute("data-rule")) {
case "patternMismatch":
if (this.validity.patternMismatch) {
span.classList.remove("hide");
}
break;
case "valueMissing":
if (this.validity.valueMissing) {
span.classList.remove("hide");
}
break;
case "typeMismatch":
if (this.validity.typeMismatch) {
span.classList.remove("hide");
}
break;
}
}
}
And right now, the disabling/enabling works IF it's the first time on input for that element, but it is "behind" all of the times after the first time. (for example, if the username is taken, the register button is enabled, but if the username is taken, the register button is disabled, the exact opposite of what I want happening).
So I thought, instead of checking for it the correct way (the way I did it in the code !(username.classList.contains("taken"))), I would reverse the logic to look like this: username.classList.contains("taken"). And that works (even though it is logically wrong and incredibly hack-y), EXCEPT for the first time a taken username is had.
What am I doing logically wrong here?
I would suggest you to have a code structure like this
function serverValidation () {
//make the ajax call here to validate all server validation
//send the success callback handler to 'clientValidations'
}
function clientValidations(){
//validate other form elements that does not require a server request here
//Then submit the form through an ajax form submit
submitFormThroughAjax();
}
function submitFormThroughAjax() {
//submit the form through ajax.
}
function onSubmit(event) {
event.preventDefault();
serverValidation();
}
//Here onSubmit should be attached to the form submit handler.
Refer:below link to know how to submit a form through ajax.
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest
This example does all the validations only after the user submits but if you want the errors to be shown instantaneously as the user interacts you need to handle it through specific form element events.
Working on form validation in jQuery. All of my validations seem to be working correctly.
See JSFiddle here.
If you submit the form with no data, all of the correct errors appear.
If you fix one of the fields, the error message for that field does not clear.
I think it probably is something wrong with my logic, but unsure if there is an easy way to try and check the validation again?
My code for submit in jQuery is here. The first four validate functions are checking for errors and displaying errors if there are any. If there are any errors with anything, the form is prevented from submitting. If there is no error, an alert is displayed and the submission is allowed. I know that the problem is that after that first if statement finds an error - there is no way to look and see if the error is fixed and to clear that error. So I'm stumped on where to go with this - would it be better off in a loop maybe?
// On Form Submission Validate Form
$("#contact_submit button").click(function(event){
error_name = validateName();
error_email = validateEmail();
error_activity = validateActivities();
isCreditIssue = validateCredit();
event.preventDefault();
var valid = true;
if ((error_name) || (error_email) || (error_activity) || (isCreditIssue)){
console.log("errors");
valid = false;
} else {
alert('GREAT! form completed');
valid = true;
}
if (valid) {
return;
}
You left out hide statements when the form values become valid at many places. Just an example (inside validateZip):
if ((!errorZip)||(zip!= 5)){
$(".error_zip").show();
errorZip = true;
console.log('zip issue');
} else {
errorZip = false;
}
You should replace it with this:
if ((!errorZip)||(zip!= 5)){
$(".error_zip").show();
errorZip = true;
console.log('zip issue');
} else {
$(".error_zip").hide();
errorZip = false;
}
I have a function which verifies if some fields have been filled out (if length > 0) before submitting. If it fails to submit, I don't want to redirect the client at all. Right now, I have the following:
function onSubmit()
{
if (verify()) //This function will throw alert statements automatically
{
document.getElementById('my_form').submit();
return void(0);
}
else
{
document.getElementById('my_form').action = null;
}
}
However, it doesn't matter if verify() returns true or not, I still redirect the client and wipe her inputted fields. How do I keep the client on the page if a required field is blank? (I don't want to lose her currently filled out form...)
Also, I can't use the slick JQuery libraries, since it's not supported on some older browsers. (I'm trying to capture the most general audience.)
This is how I would try to solve this:
document.getElementById('my_form').onsubmit = function( e ){
var event = e || window.event;
// function payload goes here.
event.returnValue = false;
if ( event.preventDefault ){ event.preventDefault(); }
return false;
}
Can be used with event delegation too.
return false to the form!
<form onsubmit="return onSubmit()">
function onSubmit()
{
if (verify()) //This function will throw alert statements automatically
{
return true;
}
else
{
return false;
}
}
to stop the form from submitting, return false from your onSubmit
i have a page on which i want to confirm if the user wants to leave.
i have to confirm only when a certain condition is met so i wrote code like this
var back=false;
back=//check if user pressed back button
window.onbeforeunload = function (e) {
alert(back); //this alerts true
if(back==true)
return false;
//e.preventDefault; --this does not work too
};
but this does not work. i mean when i click on back button this onbeforeunload still fires and i still get the confirmation message even when i m returning false.Whats can be wrong?
Thanks
Return a string if you want to offer an option to the user to abort the unload. Return nothing in other cases.
var back = false;
back = true; //Somewhere, the condition is set to true
window.onbeforeunload = function (e) {
if(back == true)
return "Are you sure to exit?";
}
$(window).bind('beforeunload',function() {
return "'Are you sure you want to leave the page. All data will be lost!";
});
$('#a_exit').live('click',function() {
$(window).unbind('beforeunload');
});
Try this. Above code is working in most of conditions.
For the sake of completeness here a more modern, recommended approach:
let warn = false;
window.addEventListener('beforeunload', e => {
if (!warn) return;
// Cancel the event
e.preventDefault();
// Chrome requires returnValue to be set
e.returnValue = '';
});
warn = true; // during runtime you change warn to true
Typically, it is better to use window.addEventListener() and the
beforeunload event, instead of onbeforeunload.
Source
The reason why your originally posted code didn't work is that false is a non-null value. If you would have returned null or undefined in the situation where you don't want to spawn a pop-up warning your code would have worked as expected.
The currently accepted answer works because JavaScript implicitly returns undefined at the end of the function.
Condition for back-end
var confirmExist = function (e) {
return true;
}
window.onbeforeunload = confirmExist;
http get, post request
.then(function(r)) {
window.onbeforeunload = null;
}
You could also consider not setting the window.beforeunload event untill your list of conditions are met.
var confirmUserToLeave = function () {
if (/* conditions are met */) {
window.unbeforeunload = function (e) {
/* whatever you want to do here */
};
} else {
window.unbeforeunload = undefined;
}
};
Then just call that method on certain events that might change the outcome of your 'conditions are met'.