I am using jQuery validation to validate my form fields. I've two fields, named "comment" and "account name". The comment field has a validation method where required is set to false. The account name field has a validation method where required is set to true. When the user clicks the submit button without entering any value on both fields, the comment field was not highlighted in green even though this field is not required. Why is that so?
$(document).ready(function () {
$.validator.setDefaults({
highlight: function (element, errorClass, validClass) {
if (element.type === "radio") {
this.findByName(element.name).addClass(errorClass).removeClass(validClass);
} else {
$(element).closest('.form-group').removeClass('has-success').addClass('has-error has-feedback');
$(element).closest('.form-group').find('span.glyphicon').remove();
$(element).closest('.form-group').append('<span class="glyphicon glyphicon-remove form-control-feedback" aria-hidden="true"></span>');
}
},
unhighlight: function (element, errorClass, validClass) {
if (element.type === "radio") {
this.findByName(element.name).removeClass(errorClass).addClass(validClass);
} else {
$(element).closest('.form-group').removeClass('has-error has-feedback').addClass('has-success has-feedback');
$(element).closest('.form-group').find('span.glyphicon').remove();
$(element).closest('.form-group').append('<span class="glyphicon glyphicon-ok form-control-feedback" aria-hidden="true"></span>');
}
}
});
$('#dataForm').validate({
rules: {
accountNameInput: {
required: true
},
commentInput: {
required: false
}
},
submitHandler: function (form) {
alert('success');
}
});
});
<form id="dataForm" method="post" action="#">
<div class="form-group">
<label class="control-label" for="commentInput">Comments</label>
<textarea class="commentInput" id="commentInput" name="commentInput" rows="5"></textarea>
</div>
<div class="form-group">
<label class="control-label" for="accountNameInput">Account name</label>
<input type="text" id="accountNameInput" name="accountNameInput"
placeholder="Account name" class="form-control font-bold" value="" />
</div>
<input type="submit" class="btn btn-primary" value="Save" id="saveButton" />
</form>
DEMO: https://jsfiddle.net/Issaki1/gud7xjy0/
Your commentInput field is not "required", therefore this field will be totally ignored for validation whenever it's left empty.
However, you can programmatically force it to validate using the .valid() method whenever the submit is clicked.
$('#saveButton').on('click', function() {
$('#commentInput').valid(); // <- force validation test on this field
});
Working DEMO: jsfiddle.net/gud7xjy0/6/
Optionally, you can also force this empty field to validate when you focusout of it...
// force eager validation on this one field
$('#commentInput').on('focusout', function() {
$(this).valid();
});
Working DEMO 2: jsfiddle.net/gud7xjy0/9/
However, this demo #2 does not make sense; since validation for the form is still "lazy" (the other field will be ignored on focusout until the submit is clicked). Option #2 only makes sense when you have your whole form setup to also implement "eager" style validation.
Related
I have several forms on my profile page. Each form has its own submit button. When a user clicks the submit button, I want the button to disappear and show a spinner.
That works fine. The issue that I am running into, is that if the user forgets to fill-out a required field, the button does not return visible. The spinner stays visible. And the page would have to be reloaded.
Jquery is not intercepting the form submission (though I am open to that if it will fix the issue), it is only toggling the spinner and button visibility.
Any help?
$("#profile-loading").hide();
$("#social-loading").hide();
$(document).ready(function () {
$("#btn_profile").on("click", function (e) {
$("#profile-loading").show();
$("#btn_profile").hide();
checkForm('#formProfile', "#btn_profile", "#profile-loading");
});
$("#btn_social").on("click", function (e) {
$("#social-loading").show();
$("#btn_social").hide();
checkForm('#formSocialMedia', "#btn_social", "#social-loading");
});
});
//Check the passed in form and toggle the buttons and the loading spinner
function checkForm($formid, $buttonid, $spinnerid) {
var emptyFields = $('#formProfile .required').filter(function () {
return $(this).val() === "";
}).length;
if (emptyFields === 0) {
console.log("no emptyFields");
} else {
console.log("emptyFields");
return false;
}
//I tried looping through each form field, but can't seem to get the form targeted.
// $($formid + '.required').each(function () {
// console.log("checkForm");
//
// var self = $(this)
// if (self.val() === '') {
// // empty
// console.log("empty");
// } else {
// // not empty
// console.log("NOT empty");
// }
// });
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form method="post" action="somelink" id="formProfile">
<input id="name" name="name" type="text" required="required">
<input id="url" name="url" type="text" required="required">
<i class="fas fa-spinner fa-2x fa-spin" id="profile-loading"></i>
<button id="btn_profile" type="submit">Save Changes</button>
</form>
<form method="post" action="someotherlink" id="formSocialMedia>
<input id="facebook" name="facebook" type="text" required="required">
<input id="instagram" name="instagram" type="text" required="required">
<i class="fas fa-spinner fa-2x fa-spin" id="social-loading"></i>
<button id="btn_social" type="submit">Save Changes</button>
</form>
There are several issues with your code, but the most important one is that you are retrieving required form elements using a required class, which does not seem to be used in your html. Instead, you can retrieve required form elements using something like
$('#formProfile [required]')
which returns all subelements of formProfile which have the required attribute. You have another issue in that the id of the form is hard-coded. Instead of hard-coding it, use the variable $formid.
$($formid + ' [required]')
Try reordering your scripts, do validation first and check if it's pass. Make sure the checkForm returns true if valid.
$("#btn_profile").on("click", function (e) {
if (checkForm('#formProfile', "#btn_profile", "#profile-loading")) {
$("#profile-loading").show();
$("#btn_profile").hide();
}
});
$("#btn_social").on("click", function (e) {
if (checkForm('#formSocialMedia', "#btn_social", "#social-loading")) {
$("#social-loading").show();
$("#btn_social").hide();
}
});
I have a form which behaves normally, with the inputs validated by simple validation. We installed a plugin, which provides some in-depth validation.
The issue arises when the plugin disables the submit button if it's validation fails on the elements it's watching.
How can I keep the submit on active state at all time without making any modification to the plugin files. However, I will have control on the page itself, so I can alter anything.
A simple JSFiddle I created to illustrate the situation:
JSFiddle
HTML
<form action="#" id="form">
Name: <input type="text" id="name" class="form-field">
<span class='error-message'>Name is required</span><br>
Age: <input type="text" id="age" class="form-field">
<span class='error-message'>Age is required</span><br>
Password: <input type="password" id="pass" class="adv-form-field">
<span class='error-message'>Advanced messages</span>
<button id="submit">Submit</button>
</form>
CSS
.error-message{
display: none;
}
JavaScript (jQuery)
// Simple validation to check if the fields have values
$(".form-field").on("blur", function(){
if(this.value == ""){
$(this).next(".error-message").css("display", "block");
} else {
$(this).next(".error-message").css("display", "none");
}
});
// Suppose this is the advanced function | we will have no control over this
$("#submit").prop("disabled", true);
$(".adv-form-field").on("blur", function(){
if(this.value == ""){
$(this).next(".error-message").css("display", "block");
$("#submit").prop("disabled", true);
} else {
$(this).next(".error-message").css("display", "none");
$("#submit").prop("disabled", false);
}
});
You can add your own event handlers after the plugin has initialised, and these will effectively override (not actually override) the plugin event handlers...
If you add this it will run on document.ready...
$(function() {
// set submit button enabled after input field blur
$(".adv-form-field").on("blur", function() {
$("#submit").prop("disabled", false);
});
// set initial state of submit button
$("#submit").prop("disabled", false);
});
I don't know which plugin you are using, but from my previous experience with form validation plugins instead of typing <button id="submit">Submit</button> use:
<input type="submit" id="submit">
I'm using the following knockout validation plugin: https://github.com/Knockout-Contrib/Knockout-Validation
I want to validate my fields when I click on the "Submit" button, not everytime when I change the input's value. How can I do that?
Javascript:
ko.validation.init({
insertMessages:false,
messagesOnModified:false,
decorateElement: true,
errorElementClass: 'wrong-field'
}, true);
var viewModel = {
firstName: ko.observable().extend({minLength: 2, maxLength: 10}),
lastName: ko.observable().extend({required: true}),
age: ko.observable().extend({min: 1, max: 100}),
submit: function() {
if (viewModel.errors().length === 0) {
alert('Thank you.');
}
else {
alert('Please check your submission.');
viewModel.errors.showAllMessages();
}
},
};
viewModel.errors = ko.validation.group(viewModel);
ko.applyBindings(viewModel);
HTML:
<fieldset>
<div class="row" data-bind="validationElement: firstName">
<label>First name:</label>
<input type="text" data-bind="textInput: firstName"/>
</div>
<div class="row" data-bind="validationElement: lastName">
<label>Last name:</label>
<input data-bind="value: lastName"/>
</div>
<div class="row">
<div class="row">
<label>Age:</label>
<input data-bind="value: age" required="required"/>
</div>
</div>
</fieldset>
<fieldset>
<button type="button" data-bind='click: submit'>Submit</button>
</fieldset>
This is my jsfiddle: http://jsfiddle.net/xristo91/KHFn8/6464/
Well, yes the validators do get fired when the observables change. But... you can trick'em with the onlyIf Option of the validators.
I made a Fiddler sample how it could work .
The question here is more... what do you want to do after the first time the user clicked....
Basically the sample puts an onlyIf condition to all validators, and the validateNow observable, decides when the validators should evaluate..basically as you wanted... in the submit method.
self.validateNow = ko.observable(false);
the onlyIf gets evaluated on all validator:
self.firstName = ko.observable().extend({
minLength: {
message:"minlength",
params: 2,
onlyIf: function() {
return self.validateNow();
}
},
and the validateNow only gets set on the submit
self.submit = function() {
self.validateNow(true);
... I also rearenged a bit the data-bindings, because your sample only puts the red box around on of the inputs.
I'm used to create my closures with constructors..so the sample is not the same "architecure" as yours, but I think you will undertsand it
i have some issues with jQuery Validator plugin.
After making it work with Scriptaculous I decided to get rid of it.
But I still have problems.
Every time I click the submit button a new label error is added to the html.
this is all the td tag,
<td align="left" colspan="2">
<input class="clase_campo" onfocus="this.className='clase_campo_en_foco';" onblur="this.className='clase_campo';" id="CampoDatos" name="CampoDatos" type="text" value="" size="20" maxlength="6" aria-required="true" aria-invalid="true"><label for="CampoDatos" class="error">Debe ingresar un dato</label>
</td>
the I click on Submit again:
<td align="left" colspan="2">
<input class="clase_campo error" onfocus="this.className='clase_campo_en_foco';" onblur="this.className='clase_campo';" id="CampoDatos" name="CampoDatos" type="text" value="" size="20" maxlength="6" aria-required="true" aria-invalid="true"><label for="CampoDatos" class="error">Debe ingresar un dato</label><label for="CampoDatos" class="error">Debe ingresar un dato</label>
</td>
and I get another LABEL tag.
Another problem is that onfocus() or lostfocus() is not cleaning those new label tags, every time I enter some chars in the field where is supposed to be required, the error don't clear.
the behavior is diferent from the samples.
Maybe I should eliminate onblur and onfocus attributes from the input tag.
Best Regards.
this is my input button
<input id="BotonAceptar" class="btn btn-sm btn-default" type="button" name="BotonAceptar" value="Aceptar" title="" onclick="this.disabled=true; /*formAgregarValor.CampoAccformAgregarValor.value='SUBMIT';formAgregarValor.submit();*/" onmouseout="this.style.fontWeight='normal';" onmouseover="this.style.fontWeight='bold';" style="font-weight: bold;">
this is my validation routine:
$( document ).ready(function(){
$('#BotonAceptar').click(function() {
if ( $("#CampoDatos").valid() &&
$("#CampoImporte").valid() ) {
formAgregarValor.CampoAccformAgregarValor.value='SUBMIT';
formAgregarValor.submit();
};
this.disabled=false;
});
$("#formAgregarValor").validate({
rules: {
CampoDatos: "required",
'CampoImporte': {
required: true,
number: true
}
},
messages: {
CampoDatos: {
required: "Debe ingresar un dato"
},
CampoImporte: "Debe ingresar un numero"
}
});
});
Quote OP:
"Every time I click the submit button a new label error is added to the html... Another problem is that onfocus() or lostfocus() is not cleaning those new label tags, every time I enter some chars in the field where is supposed to be required, the error don't clear."
I am not sure what you're trying to do with all of those inline handlers and your question is very unclear. By default, there is no duplication of the error labels and they automatically toggle when the data in the fields becomes valid/invalid.
If you just want the default functionality of the plugin, and you never explained how it should behave any differently, I think you're trying too hard. (Your code is redundant, overly complex and it's breaking the normal behavior)
Go back to the basics:
DEMO: http://jsfiddle.net/nK6f3/
I have no inline JavaScript in my demo and I've only one click handler. You only need the click handler simply because you're not using a real submit button.
$(document).ready(function () {
$('#BotonAceptar').on('click', function(e) { // capture the <button> click
e.preventDefault(); // stop any default <button> action
$("#FormAgregarValor").submit(); // submit form (automatically validates)
});
$("#FormAgregarValor").validate({ // initializes the plugin on your form
rules: {
CampoDatos: "required",
CampoImporte: {
required: true,
number: true
}
},
messages: {
CampoDatos: {
required: "Debe ingresar un dato"
},
CampoImporte: "Debe ingresar un numero"
}
});
});
As you can see, the HTML is pretty basic:
<form id="FormAgregarValor">
<input name="CampoDatos" type="text" />
<input name="CampoImporte" type="text" />
<input id="BotonAceptar" type="button" value="Aceptar" />
</form>
I am using jQuery mobile theme and jQuery validate plugin for validation purpose. The behavior of the plugin is un-expected. First see my html code
<ul data-role="listview" data-inset="true" id="updatepage">
<form method="POST" action="/update-account-info" accept-charset="UTF-8" data-ajax="false" id="updateUser">
<div data-role="content">
<li data-role="fieldcontain">
<input required="required" class="slide1el" id="first_name" data-clear-btn="true" placeholder="First Name" name="first_name" type="text" value="Awais">
<div class="error-wrapper"></div>
</li>
<li data-role="fieldcontain">
<input class="slide1el" id="last_name" data-clear-btn="true" placeholder="Last Name" name="last_name" type="text" value="Qarni">
<div class="error-wrapper"></div>
</li>
<li data-role="fieldcontain">
<input class="slide1el" id="website" data-clear-btn="true" placeholder="Website URL" name="website" type="text">
<div class="error-wrapper"></div>
</li>
<div>
<div class="ui-block-a"><button type="button" data-theme="a">Cancel</button></div>
<div class="ui-block-b"><button type="submit" data-theme="a">Submit</button></div>
</div>
</div>
</form>
</ul>
And here is my javascrip code
jQuery("#updateUser").validate({
errorElement: "label",
focusCleanup: true,
rules: {
first_name: {
required : true
},
last_name: {
required : true
},
website: {
required : true,
url : true
}
},
messages : {
first_name : {
required : 'First Name is required',
},
last_name : {
required : 'Last Name is required',
},
website : {
required : 'Website is required',
url : 'Please enter correct URL'
}
},
onkeyup: false,
errorPlacement: function (error, element) {
element.parents('li').find('div.error-wrapper').html(error)
element.parents('li').find('div.error-wrapper').find('label').removeClass('error_text');
},
// set the errorClass as a random string to prevent label disappearing when valid
errorClass : "error_text",
validClass : "ui-focus",
// use highlight and unhighlight
highlight: function (element, errorClass, validClass) {
jQuery(element).parent().addClass(errorClass).removeClass(validClass);
},
unhighlight: function (element, errorClass, validClass) {
jQuery(element).parent().removeClass(errorClass)
jQuery(element).parent().next().find('label').remove();
jQuery(element).parent().parent().next().find('label').remove();
}
});
What I am currently doing that when user submits form, I try to validate the form. If input field is empty, add a red border to the field and show the custom error message in div class=error-wrapper.
But when I submit error button, it only creates focus on first empty field it finds in DOM. And when I click anywhere in DOM, it shows the error class and highlight the textbox. I saw it in firebug, when I click submit button, It adds a ui-focus class to the empty element. When I click anywhere in DOM, the ui-focus class is automatically removed and my error classes are added.
I even tried to remove ui-focus class but it doesn't work. Kindly guide me what am I doing wrong?
What's not clear from your code is what the point of the highlight/unhighlight functions are?
I found that if I removed them and also set focusInvalid:false everything started working nicely.
So your validate call ends up looking like this (I took out the rules and messages for brevity):
jQuery("#updateUser").validate({
focusCleanup: true,
focusInvalid: false,
/* rules and messages here */
onkeyup: false,
errorPlacement: function (error, element) {
element.parents('li').find('div.error-wrapper').html(error)
element.parents('li').find('div.error-wrapper').find('label').removeClass('error_text');
},
errorClass : "error_text",
validClass : "ui-focus"
});
It works as I would expect, see here: http://jsfiddle.net/ryleyb/DC5Sz/1/