javascript remote rule not working - javascript

Hi I'm doing a validation form. I use codeigniter so I do of course a first validation with php.
I have a .js file to validate the form too. The thing is that some changes were made and now the file is no longer working properly.
When a field passes validation, a green icon appears next to the field. When it doesn't then the input box appears in red.
A field that is not working is documentn. I made a function to check if the document is already on the database. It worked on the past, now I can't figure out why is not working.
This is a snippet from the file:
form2.validate({
errorElement: 'span', //default input error message container
errorClass: 'help-inline', // default input error message class
focusInvalid: false, // do not focus the last invalid input
ignore: "",
onfocusout: function (element) {
$(element).valid();
},
rules: {
documentn: {
required: true,
minlength: 7,
maxlength: 20,
digits: true,
remote: {
url: '/checkDocNumber',
type: 'POST',
data: {
documentn: function(){
var dn = $('#documentn').val();
$("#documentn").removeData("previousValue");
return dn;
}
}
}
},
this is snippet from my admin.php:
public function updateFrontUser(){
$result = array();
$this->load->helper(array('form', 'url'));
$this->load->library('form_validation');
$this->load->database();
$this->form_validation->set_rules('documentn', 'Nro de Documento', 'required|min_length[7]|max_length[20]|is_natural');
this is function to check if document already exists on the database:
public function checkDocNumber(){
if (isset($_POST['documentn'])){
$dn = UserManager::getInstance()->getByDocument($_POST['documentn']);
if ($dn){
echo "true";
}else{
echo "false";
}
}
}
how can I check if data from remote rule is being passed to my checkDocNumber function?
EDIT
when I do a browser inspection no error appears!

Problem Solved. Just changed url from checkDocNumber to /admin/checkDocNumber
Still can't understand why it worked before with url being just checkDocNumber.
documentn: {
required: true,
minlength: 7,
maxlength: 20,
digits: true,
remote: {
url: '/admin/checkDocNumber',
type: 'POST',
data: {
documentn: function(){
var dn = $('#documentn').val();
$("#documentn").removeData("previousValue");
return dn;
}
}
}
},

Related

JQuery Validation revalidation

I'm using the JQuery Validation fine but I need to somehow re-validate a field. I have a text field that has a remote aspect and that works fine. However, there is a select box above it that may change. I just want the validation to happen again if the value of the select box changes. Is that possible?
$('#input').validate(
{
rules: {
dbname: {
required: true,
minlength: 1,
onKeyUp: false,
remote: {
type:"post",
url:'createdb/checkdbname',
data: {
catserver: function(){
return $("#catserver").val();
},
prepend: function(){
return $("#prepend").text();
}
}
}
},
dataname: {
required: true
},
clientsel: {
required: true
}
},
messages: {
dbname: {
remote: "Database Already Exists on Server"
}
},
Basically the select box catserver and dbname kinda depend on each other. I'm not sure if i'm handling this correctly. I'm using bootstrap for the form with codeigniter if that matters. Basically what happens is after I validate fine and someone changes the select value of catserver the validation of the dbname doesn't happen again unless I change the value of the dbname field.
Sure, you can bind the change event to the element that should trigger your validation:
$('.my-select-box').on('change', validate);
function validate() {
$('#input').validate(
{
rules: {
dbname: {
required: true,
minlength: 1,
onKeyUp: false,
remote: {
type:"post",
url:'createdb/checkdbname',
data: {
catserver: function(){
return $("#catserver").val();
},
prepend: function(){
return $("#prepend").text();
}
}
}
},
dataname: {
required: true
},
clientsel: {
required: true
}
},
messages: {
dbname: {
remote: "Database Already Exists on Server"
}
},
// .......
}

if statement inside jQuery Validation plugin remote rule

I have two forms: one for adding a new user and the other for user data modification.
Forms are basically the same, only difference is that when doing modification username field should not be checked if exists in database.
In Js file I do field validations. One of those validations is checking if username already exists in database. In modification this should not be considered.
This is why I thought this, but it's not working:
I differentiate the two forms with div id.
(view snippet add_user form):
<div id="add_user">
<form action="{site_url()}admin/updateFrontUser" id="form_sample_2" class="form-horizontal" method="post">
(view snippet edit_user form):
<div id="edit_user">
<form action="{site_url()}admin/updateFrontUser" id="form_sample_2" class="form-horizontal" method="post">
and then:
(js file snippet)
var algo = $('.add_user', form2);
form2.validate({
errorElement: 'span', //default input error message container
errorClass: 'help-inline', // default input error message class
focusInvalid: false, // do not focus the last invalid input
ignore: "",
rules: {
username: {
required: true,
minlength: 2,
maxlength: 15,
pattern: "[A-z](([\._\-][A-z0-9])|[A-z0-9])*[a-z0-9_]*",
remote: {
data: function(){
if (algo) {
url: '/admin/checkUsername';
type: 'POST';
};
}
}
},
The remote rule it's supposed to check if username exists. That function is already built in my admin.php. It worked previously, before I made the modifications I mentioned.
So to resume, How do I do just to use remote rule only for a new user (I mean, when using add form) ?
Please Try below rule
$().ready(function() {
$("#id_frm").validate({
rules: {
"id_question": {
required: true
},
"id_number": {
required: function(){ return $('input:radio[name=id_question]:checked').val() == 'Yes' },
minlength: 10,
minlength: 10
},
"contact_method": {
required: function(){ return $('input:radio[name=id_question]:checked').val() == 'No' }
}
},
messages: {
"id_question": {
required: "Please choose if you have an ID or not."
},
"id_number": {
required: "Please Enter ID."
},
"contact_method": {
required: "Please choose a contact method."
}
},
});
});

JQuery Validate is firing both Highlight and Unhighlight in Chrome

I am having a really strange problem with Jquery validate that only occurs in Chrome. The validation on this page seems to be firing both the Highlight and the Unhighlight functions in the .validate() function so if I dont fill out the form it cycles through each element and applies the "invalid" class in the highlight function but then for some reason it goes through and immediately applies the code in unhighlight and I cant work out why?
JS
$(document).ready(function () {
//Validation for form fields on Payment form
/*This adds a method to test whether value is equal to placeholder, and if it is, don't consider it filled out. This is necessary to circumvent IE placeholder plugin*/
jQuery.validator.addMethod("notEqual", function (value, element, param) {
return this.optional(element) || value != param;
}, "Required.");
$('#payment-form').validate({
onfocusout: function (element) {
$(element).valid();
},
rules: {
"data[Payment][card_holder]": { required: true, minlength: 2 },
"data[Payment][card_number]": { required: true, creditcard: true },
"data[User][first_name]": { required: true, notEqual: "First Name" },
"data[User][last_name]": { required: true, notEqual: "Last Name" },
"data[UserDetail][company]": { required: true },
"data[UserDetail][job_title]": { required: true },
"data[UserDetail][telephone]": { required: true },
"data[User][email]": {
required: true,
email: true,
remote: {
url: "/usermgmt/users/email_exists",
type: "post"
}
},
"data[User][password]": { required: true },
"data[Address][billing_line_1]": { required: true },
"data[Address][billing_line_2]": { required: true },
"data[Address][billing_state]": { required: true },
"data[Address][billing_postcode]": { required: true },
credit_exp_month: { required: true, notEqual: "MM", number: true, max: 12, minlength: 2, maxlength: 2 },
credit_exp_year: { required: true, notEqual: "YYYY", number: true, minlength: 2, maxlength: 4 },
"data[Payment][cvv]": { required: true, number: true, minlength: 3, maxlength: 4 },
},
errorClass: 'error',
unhighlight: function (element, errorClass, validClass) {
$(element).removeClass(errorClass).addClass(validClass);
validateIcon(element);
},
highlight: function (element, errorClass, validClass) {
$(element).addClass(errorClass).removeClass(validClass);
validateIcon(element);
}
});
function validateIcon(element) {
$(element).siblings('span.validate_icon').remove();
if ($(element).hasClass('error')) {
alert("error");
$(element).closest('li').find('label>span:first').html('<span class="validate_icon invalid"> <span class="icon-stack"><i class="icon-sign-blank icon-stack-base"></i><i class="icon-exclamation"></i></span></span>');
} else if ($(element).hasClass('valid')) {
alert("valid");
$(element).closest('li').find('label>span:first').html('<span class="validate_icon valid"> <span class="icon-stack"><i class="icon-sign-blank icon-stack-base"></i><i class="icon-ok"></i></span></span>');
}
}
});
PHP Code that handles the email exists:
public function email_exists() {
$this->autoRender = false;
if($this->request->is('post')) {
$this->RequestHandler->respondAs('json');
if(!$this->User->findByEmail($this->request->data['User']['email'])) {
echo json_encode(true);
} else {
echo json_encode(false);
}
}
}
I have also tried simply echo "true"; and echo 1; I have tried everything suggested in the comments below but regardless - the problem exists.
I had the exact same problem, and by seeing your code I might say that you have the same cause, but let's break it down.
Checking
First, let's check that my comment is relevant, and I can actually help you. Comment the remote param on your email validation set up:
"data[User][email]": {
required: true,
email: true
},
Is your problem fixed? Great, keep reading (feel free to skip to the fix section).
The problem
1. When the plugin validates, it creates a list of errors, stored into an array called "errorList".
2. Have you ever used the showErrors functionality? It's there to show all the errors, but also to target-show errors. If you want to show specific errors, or to show errors that are out of the limits of the plugin (ej.: a 60s timeout has expired), you can use that method.
3. When showing specific errors, what that method does is to add the specified error(s) to the errorList.
4. The problem is that before adding new errors that list is cleared up (I didn't write the code, but it seems that it's done in order to keep that list nice and clean, and not having two different errors of the same input).
5. Now, when the email is checked remotely we are in the same situation of a timeout. So it uses the showErrors functionality, and that means that the form is validated when click, and some seconds later (with the PHP response), the email error is shown, but clearing up the errorList. That's what is happening.
The fix
If you are not going to do explicit use of showErrors, truth is that you can comment the line where the errorList is cleared up:
showErrors: function( errors ) {
if ( errors ) {
// add items to error list and map
$.extend( this.errorMap, errors );
//this.errorList = [];
for ( var name in errors ) {
...
If you are going to do an explicit use of that method, you can try this version instead. Doesn't clear the error list, but checks that you're not adding the same error twice:
showErrors: function( errors ) {
if ( errors ) {
// add items to error list and map
$.extend( this.errorMap, errors );
for ( var name in errors ) {
var tempElem = this.findByName(name)[0];
this.errorList = jQuery.grep(this.errorList, function( error, i ) {
return error.element != tempElem;
});
this.errorList.push({
message: errors[name],
element: tempElem
});
}
Let me know if worked or you have any problem.
This code of yours can be a problem...
onfocusout: function (element) {
$(element).valid();
},
You cannot put the .valid() method inside of the .validate() method without causing some serious issues.
This is the default onfocusout function from the plugin...
onfocusout: function( element, event ) {
if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
this.element(element);
}
}
What's the purpose of your custom onfocusout function? Generally, it's not needed since the onfocusout trigger is already built into the functionality. One constructs their own onfocusout function only to over-ride the built-in default. So if you want the default onfocusout behavior, just remove the onfocusout option entirely.
If you really want to emulate something like in your code, it would need to look like this...
onfocusout: function(element, event) {
this.element(element);
}
Quote OP Comment:
"as I said im not really sure what good it would do you: (I cant get it to format here..)"
$this->RequestHandler->respondAs('json');
if(!$this->User->findByEmail($this->request->data['User']['email'])) {
return json_encode(true);
} else {
return json_encode(false);
}
It does a lot of good to show any code that could be affecting the problem, especially any code that's wrong. This could have been solved two days ago.
return is for returning to the PHP function that called this one. In other words, return will do nothing here since there is no PHP function to return to. On the other hand, echo will output from PHP... and that's what you need for jQuery Validate remote...
if (....) {
echo true;
} else {
echo false;
}
PHP return versus PHP echo
Also see: https://stackoverflow.com/a/21313309/594235

How can I detect when jQuery Validation is done, and call something based on that event?

I'm new to jQuery.
Working with jQuery validation plugin & cufon at the same time is giving me really hard time.
Basically, I want to detect event once jQuery Validation did what it had to do and call Cufon.refresh() straight after it.
$('#commentForm').validate({
rules: {
password: {
required: true,
minlength: 8,
maxlength: 8,
number: true
},
}
});
We are expecting <label class="error"> SOME TEXT </label> when form is not valid.
And once that created I want to Cufon.refresh() on that label created by jQuery Validation.
How can I detect when jQuery Validation is done, and call something based on that event?
Any help much appreciated.
Regards,
Piotr
Thanks to #Ariel - if there is a 'success' there has to be a 'not-success' as well, so..
Working code:
$('#commentForm').validate({
rules: {
password: {
required: true,
minlength: 8,
maxlength: 8,
number: true
}
},
showErrors: function(errorMap, errorList) {
this.defaultShowErrors();
Cufon.refresh();
//alert('not valid!')
},
success: function() {
//alert('valid!')
}
});
Thanks again for the idea!
Use the success option:
$('#commentForm').validate({
rules: {
password: {
required: true,
minlength: 8,
maxlength: 8,
number: true
},
}
success: function() { .... }
});
Note that you have an extra comma after the close brace for the password object. This will give an error in IE.
<script src="js/validate/jquery-1.11.1.min.js"></script>
<script src="js/validate/jquery.validate.min.js"></script>
<script src="js/validate/additional-methods.min.js"></script>
<script>
jQuery.validator.setDefaults({
success: "valid"
});
var form = $("#myform");
form.validate({
rules: {
name: {required: true, minlength: 2},
lastname: {required: true, minlength: 2}
}
});
$("#button").click(function() {
if(form.valid() == true ) { // here you check if validation returned true or false
$("body").addClass("loading");
}
})
</script>
submitHandler: { function(){ bla bla }}
This will allow you to execute code upon the completion of the validate. you will need to place a submit form snippet though, since it replaces the default handler.
EDIT:
// specifying a submitHandler prevents the default submit
submitHandler: function() {
alert("submitted!");
},
// set this class to error-labels to indicate valid fields
success: function(label) {
// set as text for IE
label.html(" ").addClass("checked");
}
You can use either to do what you want. submitHandler allows you to stop the submit and execute code instead ( you can possibly use it to perform code BEFORE you submit it ) or success to execute code after the submit.
Put it inside the errorPlacement option.
errorPlacement: function(error, element) {
error.appendTo( element.parent() );
yourCodeHere();
}
$(document).ready(function() {
$('#commentForm').submit(function(){
var validationResponse = $('#commentForm').valid();
if(validationResponse) {
// when true, your logic
} else {
// when false, your logic
return false;
}
});
$("#commentForm" ).validate({
rules: {
"first_name": {
required: true
}
},
messages: {
"first_name": {
required: "First Name can not be empty"
}
}
});
});

How to display jQuery Validation error container only on submit

I am trying to make the Validation plugin work. It works fine for individual fields, but when I try to include the demo code for the error container that contains all of the errors, I have an issue. The problem is that it shows the container with all errors when I am in all fields, but I would like to display the error container only when the user presses the submit button (but still show inline errors beside the control when losing focus).
The problem is the message in the container. When I took off the code as mentioned in the answer below for the container, the container output just displays the number of errors in plain text.
What is the trick to get a list of detailed error messages? What I would like is to display "ERROR" next to the control in error when the user presses the tab button, and to have a summary of everything at the end when he presses submit. Is that possible?
Code with all input from here:
$().ready(function() {
var container = $('div.containererreurtotal');
// validate signup form on keyup and submit
$("#frmEnregistrer").bind("invalid-form.validate", function(e, validator) {
var err = validator.numberOfInvalids();
if (err) {
container.html("THERE ARE "+ err + " ERRORS IN THE FORM")
container.show();
} else {
container.hide();
}
}).validate({
rules: {
nickname_in: {
required: true,
minLength: 4
},
prenom_in: {
required: true,
minLength: 4
},
nom_in: {
required: true,
minLength: 4
},
password_in: {
required: true,
minLength: 4
},
courriel_in: {
required: true,
email: true
},
userdigit: {
required: true
}
},
messages: {
nickname_in: "ERROR",
prenom_in: "ERROR",
nom_in: "ERROR",
password_in: "ERROR",
courriel_in: "ERROR",
userdigit: "ERROR"
}
,errorPlacement: function(error, element){
container.append(error.clone());
error.insertAfter(element);
}
});
});
First your container should be using an ID instead of a class.. (I'm going to assume that ID is 'containererreurtotal')
Then Try this..
$().ready(function() {
$('div#containererreurtotal').hide();
// validate signup form on keyup and submit
$("#frmEnregistrer").validate({
errorLabelContainer: "#containererreurtotal",
wrapper: "p",
errorClass: "error",
rules: {
nickname_in: { required: true, minLength: 4 },
prenom_in: { required: true, minLength: 4 },
nom_in: { required: true, minLength: 4 },
password_in: { required: true, minLength: 4 },
courriel_in: { required: true, email: true },
userdigit: { required: true }
},
messages: {
nickname_in: { required: "Nickname required!", minLength: "Nickname too short!" },
prenom_in: { required: "Prenom required!", minLength: "Prenom too short!" },
nom_in: { required: "Nom required!", minLength: "Nom too short!" },
password_in: { required: "Password required!", minLength: "Password too short!" },
courriel_in: { required: "Courriel required!", email: "Courriel must be an Email" },
userdigit: { required: "UserDigit required!" }
},
invalidHandler: function(form, validator) {
$("#containererreurtotal").show();
},
unhighlight: function(element, errorClass) {
if (this.numberOfInvalids() == 0) {
$("#containererreurtotal").hide();
}
$(element).removeClass(errorClass);
}
});
});
I am assuming here that you want a <p> tag around each of the individual errors. Typically I use a <ul> container for the actual container (instead of the div you used called 'containererreurtotal') and a <li> for each error (this element is specified in the "wrapper" line)
If you specify #containererreurtotal as display: none; in your CSS, then you dont need the first line in the ready function ( $('div#containererreurtotal').hide(); )
You will find the documentation for the meta option in http://docs.jquery.com/Plugins/Validation/validate#toptions
If you want to display the errors beside the inputs AND in a separate error container you will need to override the errorPlacement callback.
From your example:
...
courriel_in: "ERROR",
userdigit: "ERROR"
}
,errorContainer: container
,errorPlacement: function(error, element){
var errorClone = error.clone();
container.append(errorClone);
error.insertAfter(element)
}
// We don't need this options
//,errorLabelContainer: $("ol", container)
//,wrapper: 'li'
//,meta: "validate"
});
...
The error parameter is a jQuery object containing a <label> tag. The element parameter is the input that has failed validation.
Update to comments
With the above code the error container will not clear errors because it contains a cloned copy. It's easy to solve this if jQuery gives a "hide" event, but it doesn't exist. Let's add a hide event!
First we need the AOP plugin
We add an advice for the hide method:
jQuery.aop.before({target: jQuery.fn, method: "hide"},
function(){
this.trigger("hide");
});
We bind the hide event to hide the cloned error:
...
,errorPlacement: function(error, element){
var errorClone = error.clone();
container.append(errorClone);
error.insertAfter(element).bind("hide", function(){
errorClone.hide();
});
}
...
Give it a try
I would remove the errorContainer and then intercept the validation on postback and in there add a container-error manually like this:
$("#frmEnregistrer").bind("invalid-form.validate", function(e, validator) {
var err = validator.numberOfInvalids();
if (err) {
container.html("THERE ARE "+ err + " ERRORS IN THE FORM")
container.show();
} else {
container.hide();
}
}).validate({ ... })
I have a slightly different solution:
jQuery(document).ready(function() {
var submitted = false;
var validator = jQuery("#emailForm").validate({
showErrors: function(errorMap, errorList) {
if (submitted) {
var summary = "";
jQuery.each(errorList, function() {
summary += "<li><label for='"+ this.element.name;
summery += "' class='formError'>" + this.message + "</label></li>"; });
jQuery("#errorMessageHeader").show();
jQuery("#errorMessageHeader").children().after().html(summary);
submitted = false;
}
this.defaultShowErrors();
},
invalidHandler: function(form, validator) { submitted = true; },
onfocusout: function(element) { this.element(element); },
errorClass: "formError",
rules: {
//some validation rules
},
messages: {
//error messages to be displayed
}
});
});
I solved this problem with the following short code:
errorElement: "td",
errorPlacement: function (error, element) {
error.insertAfter(element.parent());
}
My structure is the following:
<table>
<tr>
<td>Name:</td>
<td><input type="text" name="name"></td>
</tr>
</table>
So my errors will now shown directly in a <td> behind my <input>
I don't know if the validation plugin provides an option for this, but you can probably use standard jQuery to achieve what you want. Make sure you're container is initially hidden, by setting the display style to none:
<div id="container" style="display:none;"></div>
Then you can hookup an onsubmit event to the form which will make the container visible as soon as an attempt is made to submit the form:
jQuery('#formId').onsubmit(function() {
// This will be called before the form is submitted
jQuery('#container').show();
});
Hopefully combining that with your existing code should do the trick.

Categories