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."
}
},
});
});
Related
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;
}
}
}
},
I want a asterisk to appear next to the field, and then a specific message to appear at the bottom of my form at the same time upon validation.
Currently, I have these two versions:
1) works for the asterisk appearing after the field title.
2) works for making "please fill in the last name".
However, how can I get these both to work at the same time?
Currently only the one on top of the other will work if I have them both in my file at the same time.
1) APPENDed NEXT TO FIELD LABEL VERSION
$(document).ready(function() {
// validate signup form on keyup and submit
$("#newform").validate({
errorPlacement: function(error, element) {
error.appendTo('#title-' + element.attr('id'));
},
rules: {
lastname: {
required: true,
minlength: 2
}
},
messages: {
lastname: {
required: "*",
minlength: "*"
}
}
});
});
</script>
2) MESSAGE BOX VERSION
$(document).ready(function() {
// validate signup form on keyup and submit
$("#newform").validate({
errorLabelContainer: "#messageBox",
wrapper: "li",
submitHandler: function() { alert("Submitted!")
},
rules: {
lastname: {
required: true,
minlength: 2
}
},
messages: {
lastname: {
required: "please fill in last name",
minlength: "please fix the last name"
}
}
});
});
</script>
Thanks
The answer was that there can only be one validate on the page that will be recognized.
jQuery's Validate plugin has the highlight option that can replace the asterisk method I was trying to implement.
Meanwhile, errorLabelContainer can get the messages in space down by the bottom of the form.
Both of those options can go into one Validate() without interfering with each other.
I know this question has been asked before and I have read all the previous questions and I still can't get the jQuery validator to properly validate CKEditor fields.
My form is below:
<form id="faq-form">
<p>
<label>Title:</label>
<input type="text" id="faq-title" name="faq-title" class="faq-title" />
</p>
<p>
<label for="question">Question:</label>
<textarea name="question" id="question"></textarea>
</p>
<p>
<label for="answer">Answer:</label>
<textarea name="answer" id="answer"></textarea>
</p>
<p>
<input id="submit-faq" name="submit-faq" type="submit" value="Submit" />
</p>
</form>
Both textareas are converted to CKEditor fields using:
<script>
CKEDITOR.replace('question', { toolbar : 'forum' });
CKEDITOR.replace('answer', { toolbar : 'forum' });
</script>
When I try to validate, only the title field gets validated. I am not sure what I am doing wrong. Here is my javascript code for validating (the following sits in a jQuery document ready function).
$('#faq-form').submit(function() {
// Update textareas with ckeditor content
for (var i in CKEDITOR.instances) {
CKEDITOR.instances[i].updateElement();
$.trim($('#' + i).val());
}
// Validate the form
if ( ! $('#faq-form').validate({
rules: {
'faq-title': {
required: true,
minlength: 5
},
answer: {
required: true,
minlength: 20
},
question: {
required: true,
minlength: 20
}
}
}).form()) {
console.log('Form errors');
return false;
}
Once the validation is complete, I will use a $.post method instead of a normal form get or post so I can update my page without reloading. The $.post comes after the validation method but I didn't think it was necessary to show.
I was finally able to get it working. CKEditor hides the textareas when it runs and the jQuery validator ignores hidden elements. In the validate function, this can be changed. So my new code is below:
if ( ! $('#faq-form').validate({
ignore: "input:hidden:not(input:hidden.required)",
rules: {
'faq-title': {
required: true,
minlength: 5
},
answer: {
required: true,
minlength: 20
},
question: {
required: true,
minlength: 20
}
},
messages: {
'faq-title': {
required: "The title field is required"
},
answer: {
required: "The answer field is required"
},
question: {
required: "The question field is required."
}
},
errorElement: "span",
errorPlacement: function (error, element) {
error.appendTo(element.prev());
}
}).form()) {
console.log('Form errors');
return false;
}
I also added messages and modified the element and location of the errors when they are displayed. I figured that might be helpful to anyone else who stumbles across this.
Ok lets cut it down, I have spent hours to get the error message of CKEditor in the right place, because every time it showing up on top of the CKEditor or just after the label which is not look nice.
As CKEditor hides the textarea and put its span tag right after the textarea. Please use browser tool to inspect the dom elements, then you can see the textarea is hidden.
I just adjusted the code to get the error message label/span just under the CKEditor.
$('#messageForm').validate(
{
ignore: 'input:hidden:not(input:hidden.required)',
rules: {
msgTitle: {
minlength: 2,
required: true
},
msgText: {
minlength: 2,
required: true
}
},
errorElement: "span", // can be 'label'
errorPlacement: function (error, element) {
if ($(element).attr('id') == 'msgText') {
$('#cke_msgText').after(error);
} else {
element.after(error);
}
},
highlight: function (element) {
$(element).closest('.form-group').removeClass('text-success').addClass('error');
},
success: function (element) {
element
.closest('.form-group').removeClass('error').addClass('text-success');
}
});
Here, 'msgText' is the id of the textarea which is hidden, and cke_msgText id of the ckeditor, you can find the id by inspecting the dom element, perhaps ckeditor takes the id attribute of textarea and prefix 'cke_' with it.
My guess is that CKEditor doesn't play nicely with validation, at least by default. You'd need to remove the editors before validation (CKEditor works by hiding the thing being edited and then inserting an iframe and sticking the editable content in there; when you remove the editor it shuts down the iframe and copies over the content -- at least that's from memory). My guess is that if you inspect the DOM you'll see that the content of the textareas isn't changing.
You may find NicEdit more useful in this context -- see this thread:
https://stackoverflow.com/questions/3914510/wysiwyg-editor-without-iframe
Your code:
$('#faq-form').submit(function() {
// Update textareas with ckeditor content
for (var i in CKEDITOR.instances) {
CKEDITOR.instances[i].updateElement();
$.trim($('#' + i).val());
}
if ( ! $('#faq-form').validate({
rules: {
'faq-title': {
required: true,
minlength: 5
},
answer: {
required: true,
minlength: 20
},
question: {
required: true,
minlength: 20
}
}
}).form()) {
console.log('Form errors');
return false;
}
....
You should not use .validate() inside a conditional. That's what the .valid() method is for. .validate() is only used for initializing the plugin once on DOM ready with your rules & options. Once initialized, then .valid() can be used inside conditionals to trigger a test and return a boolean.
Also, you should not have .validate() inside of submit handler. The plugin has it's own submitHandler callback function.
Your code should be changed into something like:
$(document).ready(function() {
$('#faq-form').validate({ // initialize the plugin
// rules & options,
rules: {
'faq-title': {
required: true,
minlength: 5
},
answer: {
required: true,
minlength: 20
},
question: {
required: true,
minlength: 20
}
},
submitHandler: function (form) {
// Update textareas with ckeditor content
for (var i in CKEDITOR.instances) {
CKEDITOR.instances[i].updateElement();
$.trim($('#' + i).val());
}
}
})
if ( ! $('#faq-form').valid() ) { // test the form for validity
console.log('Form errors');
return false;
}
});
Best solution I found so far, simple and elegant:
$('#form1').validate({
ignore: [],
rules: {
corpo : {
required: function()
{
CKEDITOR.instances.corpo.updateElement();
}
}
}
})
Font: http://devlog.waltercruz.com/usando-ckeditor-e-jquery-validate-juntos
<form>
<textarea class="ckeditor" id="noticeMessage" name="message"></textarea>
</form>
<script type="text/javascript" src="ckeditor/ckeditor.js"></script>
<form>
<textarea class="ckeditor" id="noticeMessage" name="message"></textarea>
</form>
<script type="text/javascript" src="ckeditor/ckeditor.js"></script>
<script type="text/javascript">
$("form").submit( function() {
var messageLength = CKEDITOR.instances['noticeMessage'].getData().replace(/<[^>]*>/gi, '').length;
if( !messageLength ) {
alert( 'Please enter a message' );
}
}
</script>
see for full reference
----------------------
http://christierney.com/2012/12/14/ckeditor-4-required-field-validation/
UPDATE
Thanks to charlietfl's comments and suggestions (and, at one point ire, lol - apologies for my faux pas), I've finally got the system checking from within Validate, and the form submission is halted when the email is sent. So I guess my question is answered, but if you'll all bear with me for one more moment, there's one last finishing touch that I could use your help with...
In my original vision, in addition to triggering a proper "Email already exists" error, I also populated a second element with some HTML that more completely explained the situation to the user and provided a link to a login form. This second element appeared and disappeared depending on the status of the field.
Is there a way to use the messages/remote section to do this as well?
Here what I have:
$(document).ready(function(){
$("#signup").validate({
errorElement: "span",
errorPlacement: function(error, element) {
error.appendTo(element.prev());
//element.prev().replaceWith(error);
},
rules: {
"email": {
required: true,
email:true,
remote: {
url: "/ajax/emailcheck.php",
type: "post",
},
},
"password": {
required: true,
minlength: 8,
},
"password-check": {
required: true,
minlength: 8,
passmatch: true,
},
"tos": {
required: true,
minlength: 6,
}
},
messages: {
email: {
required: " is Required",
email: " is Improperly Formatted",
remote: " already exists",
},
},
password: {
required: " is Required",
minlength: " requires at least 8 characters",
},
"password-check": {
required: " is Required",
minlength: " requires at least 8 characters",
passmatch: " must match the Passphrase",
},
tos: {
required: " is Required",
minlength: " requires at least 6 characters",
},
},
onkeyup: true,
onblur: true
});
And, in the ideal, I'd love something like this:
messages: {
email: {
required: " is Required",
email: " is Improperly Formatted",
remote: " already exists",
remote: {
username: function() {
var emailcheck = $('#email').val();
return $('#username_availability_result').html(emailcheck + ' is already in our system. Please log in here.');
},
},
},
},
Thanks again, and in advance, for your own ongoing attention and advice,
Z
ORIGINAL QUESTION
I'm using jQuery Validate to run routine validation on a registration form. But one of the features I wanted to add to the form's functionality was an AJAX check to determine if an email address was already in the system. The problem is that the email check function exists outside of the validate function, and so doesn't actually stop the form from submitting when necessary.
Here's my code. (The top 50 lines comprise validation and password matching. The remainder constitutes the AJAX check [which is triggered by the email field's keyup event]).
// Method adds password matching abilities to the validator
jQuery.validator.addMethod("passmatch", function(value, element) {
return $('#password').val() == $('#password-check').val()
}, "* Passwords should match");
$(document).ready(function(){
$("#signup").validate({
errorElement: "span",
errorPlacement: function(error, element) {
error.appendTo(element.prev());
//element.prev().replaceWith(error);
},
rules: {
"email": {
required: true,
email:true,
},
"password": {
required: true,
minlength: 8,
},
"password-check": {
required: true,
minlength: 8,
passmatch: true,
},
"tos": {
required: true,
minlength: 6,
}
},
messages: {
email: {
required: " is Required",
email: " is Improperly Formatted",
},
password: {
required: " is Required",
minlength: " requires at least 8 characters",
},
"password-check": {
required: " is Required",
minlength: " requires at least 8 characters",
passmatch: " must match the Password"
},
tos: {
required: " is Required",
minlength: " requires at least 6 characters",
},
}
});
//check email availability
$('#email').keyup(function(){
check_availability();
});
});
//function to check username availability
function check_availability(){
//get the username
var username = $('#email').val();
//use ajax to run the check
$.post("/ajax/emailcheck.php", { username: username },
function(result){
//if the result greater than none
if(result > 0 ){
//show that the username is not available
$('#username_availability_result').html(username + ' is already in our system. Please log in here.');
}else{
//username available.
//clear any messages
$('#username_availability_result').html('');
}
});
}
Is there a way for the check_availability() function to trigger a stop (and a start once it's cleared) so that the form can't be submitted during a state of error? Or can the whole kit and caboodle somehow be integrated into Validate using addMethod (if so, please note that I'm providing availability feedback in a specifically IDed element, not through the same element where other Validate errors appear)?
Thanks in advance for all your help and advice.
Z
Use the remote option of validation plugin that already has a built in ajax method that will bind to the input
http://docs.jquery.com/Plugins/Validation/Methods/remote#options
Alternatively required can also be a function ( will not work on keyup or blur)
email:{ required: function(){
return $('#username_availability_result').html()=='';
}
}
Also, why not reset the email field if ajax returns a duplication? Your code would likely work as is with a reset of the field
Best suggestion is use built in remote
<script language="javascript" type="text/javascript">
$(document).ready(function() {
$("#singupfrom").validate({
rules: {
'useremail': {// compound rule
required: true,
email: true,
remote:{
url: "check_email.php",
type: "post",
data:
{
emails: function()
{
return $('#singupfrom :input[name="useremail"]').val();
}
}
}
}
},
// here custom message for email already exists
messages: {
useremail: { remote: "Email already exists"}
}
});
});
</script>
<!-- your user email-->
<label>Email :</label>
<input type="text" name="useremail" id="useremail" value="" />
<!-- your user email end -->
// your php file "check_email.php" will be some thing like it
/// get or post can also be used in place of request depending on situation
$email = $_REQUEST['useremail'];
<?php
$check = "your query to check the email and returns the no of rows/ emails exists ";
if ($check == '0' or empty($check)) {
echo 'true';
} else {
echo 'false';
}
?>
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.