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.
Related
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
}
};
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'm building a form that is broken up into slides. I want to make it so that when a user clicks the arrow to move to the next slide, the form first validates whether the information he/she put in is valid for the input field. If so, it moves on and if not it alerts the use with some visual effect.
Here is the code
$('.next').click(function() {
if(indexBG === 3){
indexBG = 3;
$('#RF'+indexBG).css('display', 'block');
$('#RF'+indexBG).fadeOut(500);
$('#RF'+indexBG).fadeIn(500);
}
else {
validateIt();
}
function validateIt() {
if(!isValidEmailAddress($('#email-reg-input').val())) {
$('#email-reg-input').css("border","red solid thin");
}
else {
$('#RG1').css('background-color','green');
$('#RG1').html('33% Complete!');
}
if($('#name-reg-input').val() == ''){
$('#name-reg-input').css("border","red solid thin");
}
else {
$('#name-reg-input').css("border","green solid thin");
}
};
});
Form validation can get pretty tricky. Especially when you consider all of the different use cases and variations of junk users can enter. So, since you're already using jQuery, you might want to check out the jQuery Validation Plugin.
I have a form with some fields on. I am still learning Javascript. When my is submitted it triggers my JS which checks if the fields was submitted and then displays the errors in a which is done through innerhtml. Problem is it only display's the div for a few seconds and then finishes reloading the page and the div is not displayed anymore.
function checkradio() {
chosen = ""
len = document.cv.Radio1.length
for (i = 0; (i<2); i++) {
if (document.cv.Radio1[i].checked) {
chosen = document.cv.Radio1[i].value
}
}
if (chosen == "") {
document.getElementById('error-1').innerHTML = "Please choose a type";
document.getElementById("Radio1").focus();
}
}
You need to add
e.preventDefault();
for avoiding the default behavior.
Hence, if validation fails, the form won't be submitted.
please check whether your using normal HTML input element or ASP.NET server element. If your using Server element like then page will send back to server(reloaded) when click on button. the details you gave above is not enough.
you need to prevent the default behaviour if validation fails
you most likely do the validation on submit sth like:
$('form').submit(function(e){
check = checkradio() // let your function return true or false
if(!check){
e.preventDefault(); // add this to not submit the form
}
});
so the form will not submit if the validation fails
your tweaked validate function could look like this :
function checkradio() {
chosen = ""
len = document.cv.Radio1.length
for (i = 0; (i<2); i++) {
if (document.cv.Radio1[i].checked) {
chosen = document.cv.Radio1[i].value
}
}
if (chosen == "") {
document.getElementById('error-1').innerHTML = "Please choose a type";
document.getElementById("Radio1").focus();
return false;
}else {
return true;
}
}
I need to change the back button functionality of my phonegap project, which I've succeeded in doing without any problem. The only issue now, is that I need to further change the functionality based on if the user has a certain field selected.
Basically, if the user has clicked in a field with the id of "date-selector1", I need to completely disable the back button.
I was attempting to use document.activeElement, but it only returns the type of the element (input in this case), but I still want the functionality to work when they are in a general input, but not when they are in an input of a specific id.
EDIT
I tried all of the suggestions below, and have ended up with the following code, but still no success.
function pluginDeviceReady() {
document.addEventListener("backbutton", onBackKeyDown, false);
}
function onBackKeyDown() {
var sElement = document.activeElement;
var isBadElement = false;
var eList = ['procedure-date', 'immunization-date', 'lab-test-done', 'condition-onset', 'condition-resolution', 'medication-start-date', 'medication-stop-date', 'reaction-date'];
console.log("[[ACTIVE ELEMENT: --> " + document.activeElement + "]]");
for (var i = 0;i < eList.length - 1;i++) {
if (sElement == $(eList[i])[0]) {
isBadElement = true;
}
}
if (isBadElement) {
console.log('Back button not allowed here');
} else if ($.mobile.activePage.is('#main') || $.mobile.activePage.is('#family') || $.mobile.activePage.is('#login')) {
navigator.app.exitApp();
} else {
navigator.app.backHistory();
}
}
if you're listening for the back button you can add this if statement:
if (document.activeElement == $("#date-selector1")[0]) {
/*disable button here, return false etc...*/
}
or even better (Thanks to Jonathan Sampson)
if (document.activeElement.id === "date-selector1") {
/*disable button here, return false etc...*/
}
You can have a flag set when a user clicks on a field or you can have a click event (or any other type of event) when a user clicks on the field that should disable the back button.
From the documentation it looks like for the specific page that the backbuton is conditional on you can drop back-btn=true removing that back button.
http://jquerymobile.com/test/docs/toolbars/docs-headers.html
If you need complex conditional functionality you can just create your own button in the header or footer, style it using jquery-mobile widgets and implement your own click functionality.