I want to make this compatible for browsers which do not support HTML5 validation. Basically, all I am trying to do is give the basic error by default from the browser with HTML5 and also add a class of error to each input, label and parent div for each field that has an error which I will have some additional CSS effects such as red text/border. What is happening is I get the default error message from the browser but no error classes are added to my input, label or div. If I remove HTML5 required from one of the fields and fill out the rest of the form it will then run my function and add the error classes. Below you will see my form and my jQuery function to add the error classes.
What I think is happening is when HTML5 finds an error it is not running my submit function which would add the error classes. I have figured I could trigger the invalid bind function for each input and add the error classes but I then don't think I would have any validation if the browser didn't support HTML5 validation.
jQuery portion:
$('#contact_us_form').submit(function() {
var error_count = 0;
$('#contact_us_form div').each(function() {
$(this).removeClass('error');
});
$('#contact_us_form input').each(function() {
$(this).removeClass('error');
});
$('#contact_us_form label').each(function() {
$(this).removeClass('error');
});
if ($('#fname').val() == '') {
error_count++;
$('#fname').parent('div').addClass("error");
$('#fname').addClass("error");
$('label[for="fname"]').addClass("error");
}
if ($('#lname').val() == '') {
error_count++;
$('#lname').parent('div').addClass("error");
$('#lname').addClass("error");
$('label[for="lname"]').addClass("error");
}
if ($('#email').val() == '') {
error_count++;
$('#email').parent('div').addClass("error");
$('#email').addClass("error");
$('label[for="email"]').addClass("error");
} else if (!isValidEmailAddress( $('#email').val() ) ){
error_count++;
$('#email').parent('div').addClass("error");
$('#email').addClass("error");
$('label[for="email"]').addClass("error");
}
if ($('#phone').val() == '') {
error_count++;
$('#phone').parent('div').addClass("error");
$('#phone').addClass("error");
$('label[for="phone"]').addClass("error");
} else if (!isPhone($('#phone').val())) {
error_count++;
$('#phone').parent('div').addClass("error");
$('#phone').addClass("error");
$('label[for="phone"]').addClass("error");
}
if ($('#message').val() == '') {
error_count++;
$('#message').parent('div').addClass("error");
$('#message').addClass("error");
$('label[for="message"]').addClass("error");
}
if (error_count == 0) {
submitFormWithAjax();
}
return false;
});
HTML form:
<form class="form form_careers" action="#" id="contact_us_form">
<fieldset>
<legend>Contact Information</legend>
<div class="field-name-first">
<label for="fname" class="inlined">First Name</label>
<input accesskey="f" class="input-text" id="fname" name="fname" required tabindex="1" type="text" value="" />
</div>
<div class="field-name-last">
<label for="lname" class="inlined">Last Name</label>
<input accesskey="l" class="input-text" id="lname" required tabindex="2" type="text" />
</div>
<div class="field-email-primary">
<label for="email" class="inlined">Email</label>
<input accesskey="e" class="input-text" id="email" required tabindex="3" type="email" />
</div>
<div class="field-phone-primary">
<label for="phone" class="inlined">Phone</label>
<input accesskey="p" class="input-text" id="phone" required tabindex="4" type="tel" />
</div>
<div class="field-message-comments">
<label for="message" class="inlined">Message/Comments</label>
<textarea accesskey="m" class="" id="message" required tabindex="5"></textarea>
</div>
<!--input class="cta_button cta_primary" tabindex="7" type="submit" value="Contact Us" /-->
<button class="cta_button cta_primary" tabindex="6">Contact Us</button>
</fieldset>
</form>
You could use a framework like modernizr to detect if the document supports the invalid event. While initializing your app, check to see if invalid is a supported event. If so, bind to invalid, if not bind to submit. It's a pretty robust framework (customizable and relatively small) for detecting support of various features.
This question might be of some help as well:
How to bind to the submit event when HTML5 validation is used?
What you are looking for is a polyfill for HTML5 validation.
This will basically, use javascript validation in cases where the clients browser is lacking. Polyfills are implemented in cases where a browser doesn't support the feature, which leads toward a natural, and optimized web browsing experience for the user.
This is a good resource for HTML5 form polyfills:
https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills#web-forms
On polyfills:
http://en.wikipedia.org/wiki/Polyfill
Related
I have a some custom validation for a small input form, that checks if a field is required. If it is a required field it alerts the user, if there is no value. At the moment it will validate all inputs other than check boxes.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<div class="ss-item-required">
<label>Question: What is your name?</label>
<input type="text" name="name" id="name"></input>
</div>
<div class="ss-item-required">
<label>Question: What is your email?</label>
<input type="text" name="email" id="email"></input>
</div>
<div class="ss-item-required">
<label>Question: What is your address?</label>
<textarea name="address" rows="8" cols="75" id="address"></textarea>
</div>
<div class="ss-item-required">
<label>Do you agree to out terms?</label>
<input type="checkbox" name="Check_0">
</div>
Submit
</form>
<script>
function formcheck() {
var fields = $(".ss-item-required")
.find("select, textarea, input").serializeArray();
$.each(fields, function(i, field) {
if (!field.value)
alert(field.name + ' is required');
});
console.log(fields);
}
</script>
If anyone can work out how to include validation of check boxes, it would be much appreciated.
Even though some answers already provide a solution, I've decided to give mine, that will validate every required input in your form, regardless of being a checkbox (maintaining your each loop).
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<div class="ss-item-required">
<label>Question: What is your name?</label>
<input type="text" name="name" id="name">
</div>
<div class="ss-item-required">
<label>Question: What is your email?</label>
<input type="text" name="email" id="email">
</div>
<div class="ss-item-required">
<label>Question: What is your address?</label>
<textarea name="address" rows="8" cols="75" id="address"></textarea>
</div>
<div class="ss-item-required">
<label>Do you agree to out terms?</label>
<input type="checkbox" name="Check_0">
</div>
Submit
</form>
<script>
function formcheck() {
var fields = $(".ss-item-required")
$.each(fields, function(i, field) {
field=$(field).find('input, select, textarea')[0]
if (!field.value || (field.type=='checkbox' && !field.checked))
alert(field.name + ' is required');
});
}
</script>
The problems were:
serializeArray() would try to get the value from your checkbox, and because it returned nothing, the checkbox input was never added to fields!
Checkboxes don't have a property value, instead they are checked
There is more than one way to determine this:
Check the length of the JQuery wrapped set that queries for only checked checkboxes and see if it is 1:
if($("input[name='Check_0']:checked").length === 1)
Check the checked property of the DOM element itself (which is what I'm showing below) for false. To extract the DOM element from the JQuery wrapped set, you can pass an index to the wrapped set ([0] in this case), which extracts just that one item as a DOM element and then you can use the standard DOM API.
if(!$("input[type='checkbox']")[0].checked)
NOTE: It's important to understand that all client-side validation can be easily bypassed by anyone who really wants to. As such, you
should always do a second round of validation on the server that will
be receiving the data.
FYI: You have some invalid HTML: There is no closing tag for input elements and for label elements, you must either nest the element that the label is "for" inside of the label or you must add the for attribute to the label and give it a value of the id of the element that the label is "for". I've corrected both of these things below:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<div class="ss-item-required">
<label for="userName">Question: What is your name?</label>
<input type="text" name="userName" id="userName">
</div>
<div class="ss-item-required">
<label for="email">Question: What is your email?</label>
<input type="text" name="email" id="email">
</div>
<div class="ss-item-required">
<label for="address">Question: What is your address?</label>
<textarea name="address" rows="8" cols="75" id="address"></textarea>
</div>
<div class="ss-item-required">
<label for="Check_0">Do you agree to out terms?
<input type="checkbox" name="Check_0">
</label>
</div>
Submit
</form>
<script>
function formcheck() {
var fields = $(".ss-item-required")
.find("select, textarea, input").serializeArray();
$.each(fields, function(i, field) {
if (!field.value){
alert(field.name + ' is required');
}
});
// Check to see if the input is a checkbox and if it's checked
if(!$("input[type='checkbox']")[0].checked){
alert("You must agree to the terms to continue.");
}
}
</script>
Personally (and I'm far from alone on this), the use of JQuery is way overused in today's world. When it came out, the standard DOM API wasn't as mature as it is now and JQuery made DOM element selection and manipulation very simple. Back then, JQuery was a Godsend.
Today, the DOM API has matured and much of what we use to rely on JQuery to make easy, can be done just as easily without JQuery. This means you don't have to reference the JQuery library at all (faster page loading) and you're code follows standards.
If you're interested, here's your code without JQuery:
<form>
<div class="ss-item-required">
<label for="userName">Question: What is your name?</label>
<input type="text" name="name" id="userName">
</div>
<div class="ss-item-required">
<label for="email">Question: What is your email?</label>
<input type="text" name="email" id="email">
</div>
<div class="ss-item-required">
<label for="address">Question: What is your address?</label>
<textarea name="address" rows="8" cols="75" id="address"></textarea>
</div>
<div class="ss-item-required">
<label for="Check_0">Do you agree to out terms?
<input type="checkbox" name="Check_0">
</label>
</div>
Submit
</form>
<script>
function formcheck() {
// Get all the required elements into an Array
var fields = [].slice.call(document.querySelectorAll(".ss-item-required > *"));
// Loop over the array:
fields.forEach(function(field) {
// Check for text boxes or textareas that have no value
if ((field.type === "text" || field.nodeName.toLowerCase() === "textarea")
&& !field.value){
alert(field.name + ' is required');
// Then check for checkboxes that aren't checked
} else if(field.type === "checkbox" && !field.checked){
alert("You must agree to the terms to continue.");
}
});
}
</script>
I'm trying to build a simple contact form for the newsletter subscription, the CF has just one input field (email) and the submit button. I used type="email" of HTML5 to check the the email and on the new browsers I get the default validation message:
This doesn't happen when I use older browsers obviously so I used the JS alert in case the user is using the old browsers, but this is not what I'd like.
I would like to get the same message (browser default) on all the browsers.
Here my code:
HTML
<div class="newsletter-wrap-flex margin-top-div">
<div class="newsletter-title">
<span>
NEWSLETTER
</span>
</div>
<div class="newsletter-form">
<form id="newsletter-cf" method="post" action="">
<input id="contact-email" type="email" placeholder="Your email" required/>
<input id="contact-send" class="submit" type="submit" value="Subscribe" />
</form>
<div id="message-sent">Congratulation! Your request has been sent.</div>
</div>
</div>
JS
function checkEmail(inputvalue) {
var pattern = /^([a-zA-Z0-9_.-])+#(([a-zA-Z0-9-])+.)+([a-zA-Z0-9]{2,4})+$/;
return pattern.test(inputvalue);
}
$('#newsletter-cf').submit(function () {
var email = document.getElementById("contact-email").value;
if (!checkEmail(email))
{
alert('Email address is invalid');
return false;
}
$("#newsletter-cf").slideUp("slow");
$("#message-sent").slideDown("slow");
return false;
});
I've read there could be some ways like Modernizr but I've never used them before so I don't really know how to start.
Any suggestions?
This is my first post so don't judge me if i do something wrong because i'm still learning but i have a question i'm making a form and i have a problem. When i left the button without any extra stuff when i tested the form i got as many entries as many times i clicked the button so i used a code snippet from here in JS and made the button so it disappears, problem is when i don't fill the form correctly it doesn't send the entry, so the question is how can i add the condition in form so the button only disappears when every field is written correctly? I would add the whole html but it's houndreds of lines of code now since it's pretty much where i test things here is the form code though.
My other thought was to maybe try to edit the php code, but to be honest i have no knowledge of that because my friend made that.
I also searched google and here for some tips but couldn't find any, thanks for help in advance.
$("#hideme").click(function(){
$(this).hide();
});
<form method="post" action="thankyou.php" style="overflow:hidden" class="accident-form4">
<input type="hidden" name="lang" value="pl">
<div class="form-group required">
<label for="name">Imię i nazwisko<span></span></label>
<input type="text" class="form-control inputToUpper" name="firstname" placeholder="Andrzej Kowalski" required="required" pattern=".*\S+.*" title="Wpisz swoje imię">
</div>
<div class="form-group required">
<label for="email">Email<span></span></label>
<input type="email" class="form-control" required="required" name="email" placeholder="np. andrzej.kowalski#gmail.com" title="Wpisz poprawny adres email!" pattern="[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,4}$">
</div>
<div class="form-group">
<label for="tel">Numer telefonu<span></span></label>
<input type="text" name="tel" placeholder="079 1234 5678" class="form-control" required="required" size="12" value="">
</div>
<label for="hour">Preferowana godzina kontaktu</label>
<select class="form-control" name="hour" placeholder="" title="" />
<option>Dowolna</option>
<option>Rano</option>
<option>Po południu</option>
<option>Wieczorem</option>
</select>
<input type="submit" name="lead" class="send" id="hideme" value="ROZPOCZNIJ CLAIM →">
</form>
you can simply check the value of the required fields before hiding the button.
$("#hideme").click(function(){
if (document.getElementsByName('firstname')[0].value != '' &&
document.getElementsByName('email')[0].value != '' &&
document.getElementsByName('tel')[0].value != '') {
$(this).hide();
}
});
or use your RegExp in Javascript again.
$("#hideme").click(function(){
if (document.getElementsByName('firstname')[0].value.match (/.*\S+.*/) &&
document.getElementsByName('email')[0].value.match (/[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,4}$/) &&
document.getElementsByName('tel')[0].value.match (/[0-9]+/)) {
$(this).hide();
}
});
that should to the trick (but i didn't test it).
So I guess for context, here is an example from the parsley.js documentation.
<form id="demo-form" data-parsley-validate>
<div class="first">
<label for="firstname">Firstname:</label>
<input type="text" name="firstname" data-parsley-range="[4, 20]" data-parsley-group="block1" />
<label for="lastname">Lastname:</label>
<input type="text" name="lastname" data-parsley-range="[4, 20]" data-parsley-group="block1" />
</div>
<hr></hr>
<div class="second">
<label for="fullname">Fullname:</label>
<input type="text" name="fullname" data-parsley-range="[8, 40]" data-parsley-group="block2" />
</div>
<div class="invalid-form-error-message"></div>
<input type="submit" class="btn btn-default validate" />
</form>
<script type="text/javascript">
$(document).ready(function () {
$('#demo-form').parsley().subscribe('parsley:form:validate', function (formInstance) {
// if one of these blocks is not failing do not prevent submission
// we use here group validation with option force (validate even non required fields)
if (formInstance.isValid('block1', true) || formInstance.isValid('block2', true)) {
$('.invalid-form-error-message').html('');
return;
}
// else stop form submission
formInstance.submitEvent.preventDefault();
// and display a gentle message
$('.invalid-form-error-message')
.html("You must correctly fill the fields of at least one of these two blocks!")
.addClass("filled");
return;
});
});
</script>
Let's say I have a hidden div called "checkmark". How would I show this div upon validation of the firstname field?
I should also clarify that I have read the documentation, but still don't understand how to accomplish what I'm trying to do here, so posting a link to the documentation is not really going to be helpful unless you are using it in your answer.
You should use Parsley's Events. Since you want to display or hide something based on a field validation, you should use parsley:field:success and parsley:field:error.
Working example (with jsfiddle):
<form id="demo-form" data-parsley-validate>
<div class="first">
<label for="firstname">Firstname:</label>
<input type="text" name="firstname" data-parsley-range="[4, 20]" data-parsley-group="block1" required />
<div class="hidden" id="checkmark">This message will be shown when the firstname is not valid </div>
<label for="lastname">Lastname:</label>
<input type="text" name="lastname" data-parsley-range="[4, 20]" data-parsley-group="block1" />
</div>
<hr></hr>
<div class="second">
<label for="fullname">Fullname:</label>
<input type="text" name="fullname" data-parsley-range="[8, 40]" data-parsley-group="block2" />
</div>
<div class="invalid-form-error-message"></div>
<input type="submit" class="btn btn-default validate" />
</form>
<script>
$(document).ready(function () {
$('#demo-form').parsley().subscribe('parsley:form:validate', function (formInstance) {
// if one of these blocks is not failing do not prevent submission
// we use here group validation with option force (validate even non required fields)
if (formInstance.isValid('block1', true) || formInstance.isValid('block2', true)) {
$('.invalid-form-error-message').html('');
return;
}
// else stop form submission
formInstance.submitEvent.preventDefault();
// and display a gentle message
$('.invalid-form-error-message')
.html("You must correctly fill the fields of at least one of these two blocks!")
.addClass("filled");
return;
});
$.listen('parsley:field:error', function(ParsleyField) {
if(ParsleyField.$element.attr('name') === 'firstname') {
$("div#checkmark").addClass('show').removeClass('hidden');
}
});
$.listen('parsley:field:success', function(ParsleyField) {
if(ParsleyField.$element.attr('name') === 'firstname') {
$("div#checkmark").addClass('hidden').removeClass('show');
}
});
});
</script>
And here's what I did:
Added a div with ìd=checkmark after the firstname field (with a hidden class, since you're using Bootstrap).
Added this block of javascript:
$.listen('parsley:field:error', function(ParsleyField) {
if(ParsleyField.$element.attr('name') === 'firstname') {
$("div#checkmark").addClass('show').removeClass('hidden');
}
});
$.listen('parsley:field:success', function(ParsleyField) {
if(ParsleyField.$element.attr('name') === 'firstname') {
$("div#checkmark").addClass('hidden').removeClass('show');
}
});
This code will listen to the validation of every input validated by Parsley. This means that when the field lastname fails, the code inside $.listen('parsley:field:error', function(ParsleyField) { will be executed. This is why I used an if to check if the attr name is firstname.
Then you show or hide the div based on the validation result.
Added required to the field, so the message is displayed when you click on the button.
I want to validate my fields using AngularJS's own form validation. However, I only want to check some of the fields when other fields have data. E.g.
<form novalidate name="myForm" ng-submit="submitThisForm()">
<h1>Shipping address</h1>
<!-- These are the inputs -->
<input name="sAddress1" type="text" ng-model="sAddress1" required>
<input name="sAddress2" type="text" ng-model="sAddress2" required>
<input name="sAddress3" type="text" ng-model="sAddress3">
<!-- These are the errors -->
<div class="error" ng-show='(myForm.sAddress1.$invalid) && myForm.submitted'>Required</div>
<div class="error" ng-show='(myForm.sAddress2.$invalid) && myForm.submitted'>Required</div>
<h1>Billing address (if different)</h1>
<!-- These are the inputs -->
<input name="bAddress1" type="text" ng-model="bAddress1" required>
<input name="bAddress2" type="text" ng-model="bAddress2" required>
<input name="bAddress3" type="text" ng-model="bAddress3">
<!-- These are the errors -->
<div class="error" ng-show='(myForm.bAddress1.$invalid) && myForm.submitted'>Required</div>
<div class="error" ng-show='(myForm.address2.$invalid) && myForm.submitted'>Required</div>
</form>
Basically, the Billing address is optional, but once any part of it is filled in, bAdress1 and bAddress2 become Required. How do I achieve this?
(The variable myForm.submitted is set to false on page load, and then set to true when the form is submitted, so it only shows once validation has taken place.) I prefer vanilla JS answers, but I am using jQuery for this project, so that is also okay.
EDIT: Here's the answer with a pretty, formatted layout:
In the HTML file:
<input name="bAddress1" type="text" ng-model="bAddress1" ng-required="doWeNeedThis()"/>
<input name="bAddress2" type="text" ng-model="bAddress2" ng-required="doWeNeedThis()"/>
<input name="bAddress3" type="text" ng-model="bAddress3"/>
In the JS file:
$scope.doWeNeedThis = function() {
if((document.getElementsByName("bAddress1")[0].value != "")
|| (document.getElementsByName("bAddress2")[0].value != "")
|| (document.getElementsByName("bAddress3")[0].value != "")) {
return true;
} else {
return false;
}
};
Many thanks to Davin for the quick (and complete) answer.
ng-required will allow you to run an expression to determine whether the field is required or not.
<input name="bAddress1" type="text" ng-model="bAddress1" ng-required="doWeNeedThis()">
ng-required is documented with form.
So, in your example, you could implement doWeNeedThis() function in your controller and check the values of your model to determine if the input should be required or not.
Otherwise, in simple cases, you can just write the expression directly into the ng-required expression:
<input name="bAddress1" type="text" ng-model="bAddress1" ng-required="bAddress1 || bAddress2">