I really was trying to avoid asking this question. I have seen quite a few posts on SO regarding this plugin but they still didn't quite get it for me. Right now I have a new account registration form and I'm trying to write a custom method for validating a unique username. I would like to think that the following should work:
$.validator.addMethod(
"uniqueUsername",
function(value, element) {
$.post(
"http://" + location.host + "/scripts/ajax/check_username.php",
{
username: value
},
function(response) {
if(response == 'true') {
return true;
} else {
return false;
}
}
);
},
"This username is already taken."
);
Unfortunately it seems like the plugin moves on regardless of the callback function. I found someone suggest doing something like the following:
var result = false;
$.validator.addMethod(
"uniqueUsername",
function(value, element) {
$.post(
"http://" + location.host + "/scripts/ajax/check_username.php",
{
username: value
},
function(response) {
if(response == 'true') {
result = true;
} else {
result = false;
}
}
);
return result;
},
"This username is already taken."
);
But it seems to have a delay since it stores the value, then on the next event will set whatever the value is. What do you guys recommend?
Since this is an asynchronous check, there needs to be more around it (you can't return a value from a function like this, it'll always be false in your case). The built-in method is remote, used like this:
$("form").validate({
rules: {
username: {
remote: {
url: "http://" + location.host + "/scripts/ajax/check_username.php",
type: "post"
}
}
}
});
This will POST a username: valueofElement since the rule is for the element named username. Your server-side script should return true if the validation should pass, false otherwise...so false if the user name is already taken.
You can read more about the remote option here, including how to pass additional data arguments if needed.
js code
username: {
required: true,
minlength: 5,
remote: '/userExists'
},
Php code to check if exist and return messages
public function userExists()
{
$user = User::all()->lists('username');
if (in_array(Input::get('username'), $user)) {
return Response::json(Input::get('username').' is already taken');
} else {
return Response::json(Input::get('username').' Username is available');
}
}
Related
This question already has answers here:
How to respond to jQuery Validation remote?
(1 answer)
jQuery Validate remote method usage to check if username already exists
(2 answers)
Closed 2 years ago.
I'm using the jQuery validator's remote method to determine if an email address already exists in our SaaS platform.
The code below is what we are using and it's fine. However, we would like to ideally return some information about the existing user, so that we may display a link to the existing patient's profile.
I've scoured the validator docs and can't seem to find any way to handle return parameters other than true/false. Is this a limitation of the remote method?
jQuery
form.validate({
rules: {
email: {
remote: {
url: "CheckEmailExists.php",
type: "post"
}
}
},
messages: {
email: {
remote: "This email address is already assigned to an existing patient"
}
},
});
PHP
$existingUserQuery = "SELECT tbl_patients.patient_id FROM tbl_patients WHERE tbl_patients.patient_email = :email";
$getUser = $pdo->prepare($existingUserQuery);
$getUser->bindparam(":email", $email);
$getUser->execute();
$numCount = $getUser->rowCount();
if ($numCount > 0) {
echo 'false';
} else {
echo 'true';
}
You can create a custom method and within the method do run your own remote call via AJAX. Then in your php, return a JSON object with the values that you want to use.
jQuery.validator.addMethod("validatemmail", function(value, element) {
var _is_valid = false;
var qry = {"email" : value};
$.ajax({
type: "POST",
url: "CheckEmailExists.php",
data: qry,
done: function(data){
if(data.error == "new"){
_is_valid = true;
console.log(data.patient_name);
}
else{
_is_valid = false;
}
return this.optional(element) || _is_valid );
}
});
}, "This email address is already assigned to an existing patient");
$('validatorElement').validate({
rules : {
email : { validatemmail : true }
}
});
Your PHP:
$return = [];
if ($numCount > 0) {
$return["error"] = "exists";
$return["patient_name"] = "John";
} else {
$return["error"] = "new";
}
header('Content-Type: application/json');
echo json_encode($return);
The original idea:
jQuery Validate Plugin - How to create a simple custom rule?
My issue using the validation plugin is with the remote call specifically.
The remote checks to ensure the employee id is valid from the db. If it is valid then it returns a json string with the employee info (first name, last name, supervisor name, and facility name).
The issue is if I return that json string using the complete: function the empid field stays invalid with the error class, and will not allow the form to submit even though everything is valid. If I just return true from the remote call the empID field is valid and the form will submit (assuming the other fields are completed).
Is there a specific parameter in the json callback that needs to be set to true for the remote: call to finish and be true? I am lost as to how to fix this problem, so any help would be much appreciated! See below for the related code.
var ajax_data = new Object;
$('#vpnRequest').validate({
rules: {
empID: {
//required: true,
//minlength: 4,
remote: {
url: "checkEmpID.php",
dataFilter: function(data) { ajax_data = data; return data;},
complete: function() {
var jsonObj = new Object;
jsonObj = jQuery.parseJSON(ajax_data);
var success = jsonObj.status;
if(success == 'false'){
//return success;
}else if(success == 'true'){
$('#fName').val(jsonObj.fName);
$('#lName').val(jsonObj.lName);
$('#superName').val(jsonObj.supervisorFName+" "+jsonObj.supervisorLName);
$('#facilityName').val(jsonObj.facilityName);
$('#empID').addClass('stuff');
$('#empID').removeClass('stuff');
//return success;
}
}
}
}
},
messages: {
empID:{
required: "This field is required",
remote: "Invalid Employee ID"
}
}
});
PHP file empID checker:
$string[status] = 'true';
$string[fName] = ucwords(strtolower($row['empFirstName']));
$string[lName] = ucwords(strtolower($row['empLastName']));
$string[supervisorFName] = $superFName;
$string[supervisorLName] = $superLName;
$string[facilityName] = $facilityName;
}
$response = json_encode($string);
echo $response;
} else {
$response = json_encode($valid);
echo $response;
}
Adding to the validator code itself:
if ($.isFunction(param.validateResult)) response = param.validateResult(response);
from the site http://plugins.jquery.com/content/custom-function-handle-returned-data-remote-function appears to work extremely well, as it validates properly and submits the form. If anyone wants to test further to ensure fringe cases that would be great but this should definitely be added to the validator plugin to extend its capabilities.
I have written this ajax request for username checking...
function check_username() {
var username = $("#username").val();
$('.loading').fadeIn().delay(100);
$.post("ajax.php", {
username: $('#username').val(),
}, function (response) {
$('.error, .success').hide();
setTimeout(function () {
$('.loading').hide();
finishAjax('username', response);
}, 1000);
});
return false;
}
function finishAjax(id, response) {
$('#' + id).after(response).fadeIn(1000);
}
It all works fine just a couple of questions,
Can this code be improved in any way, this is the first ever one I have wrote so I wouldn't know.
Is there a way to make this a function for all my ajax requests rather than just username checking, so it can be used for email checking and such too. I am not sure on how to make a function like that would I have to pass variables on my onblur event which is attached to my form, at the minute it looks like this.
Is there a way to stop the ajax from running if the same error is there as previous, ie, string length should be over 3, so someone inputs AJ, and the error message 'must be over 3 characters' comes up, it the user then triggers the onblur event again, with the value of AJ, or CG, then the same error comes up, triggering a script that is useless and using memory.
Is there a way to make the ajax request with every character the user enters?
My ajax php is as follows...
<?php
require('dbc.php');
if (isset($_REQUEST['username'])) {
$q = $dbc -> prepare("SELECT username FROM accounts WHERE username = ?");
$q -> execute(array($_REQUEST['username']));
if (strlen($_REQUEST['username']) < 3) {
echo '<div class="error">Has to be at least 3 characters</div>';
}
elseif ($q -> rowCount() > 0) {
echo '<div class="error">Username already taken</div>';
}
else {
echo '<div class="success">Username available</div>';
}
}
?>
To answer 1 & 2. I would turn it into a plugin and do something along these lines.
$.fn.checkValid = function(options)
{
var response = function(response) {
var setClass = '';
var $span = $(this).data('checkValidTip');
if ($span)
{
$span.remove();
}
if (response === undefined) return;
setClass = (response.valid ? 'valid' : 'invalid');
var $span = $('<span>' + response.msg + '</span>');
$(this)
.data('checkValidTip', $span)
.after($span);
$span.hide()
.fadeIn(1000)[0]
.className = setClass;
};
var ajaxOptions = {
type: 'GET',
url: 'ajax.php',
success: response,
dataType: 'json'
};
this.each(function() {
var that = this;
var ajaxRequest = ajaxOptions;
ajaxRequest.data = {};
ajaxRequest.data[options.key] = this.value;
ajaxRequest.context = that
$.ajax(ajaxRequest);
});
};
Usage
$('#username, #email').blur(function() {
$(this).checkValid({ key: this.id });
});
PHP changes
You should make your PHP function return a JSON, instead of HTML i.e.
<?php
// Do your sql statements here, decide if input is valid or not
$arr = array('valid' => $is_valid,
'msg' => $error_or_good_msg
);
echo json_encode($arr);
/* For example will output:
{
"valid": "false",
"msg": "<b>Error: Must be at least 2 characters</b>"
}
Which can be read directly as response.valid
or response.msg from within response() function
*/
To answer question 3: short answer is no. For this to work, you should have basic validation in JS. The best option would be to use a plugin that uses objects for validation parameters, that way you can output your validation requirements dynamically from your database, from within PHP using json_encode i.e. your output format would be:
var validations = {
username: {
min_chars: 4,
max_chars: 10,
valid_chars: 'qwertyuiopasdfghjklzxcvbnm_-'
},
email: {
regex: /./ //your magic regex here
}
};
jsFiddle
http://jsfiddle.net/sqZfp/2/
To answer 4, just change the event as above from .blur to .keyup should do the trick.
I am sure this is probably something simple that i am not doing. Running livevalidation.js jquery plugin (livevalidation.com). It provides for custom function callbacks. I am trying to check for username availability. The server side is working fine and I am getting the proper responses back in my data var...
Here is my JS:
Validate.Username = function(value, paramsObj) {
var paramsObj = paramsObj || {};
var message = paramsObj.failureMessage || "Username is not available";
var isSuccess = true;
$.post("<?php echo fURL::getDomain(); ?>/ajax/username",
function(data) {
if (data.status === 'notavailable')
{
Validation.fail('oops, not available.');
}
});
};
I am calling it using:
var username = new LiveValidation('username', { validMessage: curr_username + "is available!" });
username.add( Validate.Presence, { failureMessage: "Choose a username" });
username.add( Validate.Username, { failureMessage: "Username is not available." } );
The problem I am getting is:
Uncaught ReferenceError: Validation is not defined
If I put the Validation.fail() outside of my .post() function it works fine. So am pretty sure it is because it's not able to be referenced inside the .post() function.
I've tried using a callback function
if (data.status === 'notavailable')
{
status_not_available();
}
I get the same error.
I realize this is something probably extremely simple, but any help would be appreciated. Thank you in advance.
i am having the same issue.
Ive found the following, http://forum.jquery.com/topic/ajax-return-value-on-success-or-error-with-livevalidation but have not been able to get it working.
BUT YES! At this very moment i made som (crappy) javascript addon that made it behave, i think :)
This is what i use.
function check_avail(name, id, postUrl)
{
var dataVal = name+'='+$(id).val();
var isaccepted = ''
$(id).next('div').remove();
$(id).after("Undersøger om "+name+" er ledigt");
$.ajax({
url: postUrl,
cache: false,
type: 'post',
dataType: 'json',
data: dataVal,
async: false,
success: function(data) {
if( data.success == 'true' )
{
$('#'+name+'-availability').remove();
//return false;
isaccepted = false;
}
if( data.success == 'false' )
{
$('#'+name+'-availability').remove();
// name.destroy();
isaccepted = true;
}
}
});
if (isaccepted == false) {
return false;
} else{
return true
};
}
And
f1.add( Validate.Custom, { against: function() {
return check_avail( 'brugernavn', '#ft001', 'usernamecheck.asp' );
}, failureMessage: 'Brugernavnet er optaget' } );
Hope it helps you :)
The json query you can read about on the link in the begining :)
(I am not at all skilled at javascript, and the "isaccepted" solution could problalby be made a lot better)
try to change it from Validation.fail to Validate.fail
try wrapping it in another function and try putting your validateStatus(status) function both inside and outside your Validate.Username function. example below is inside
Validate.Username = function(value, paramsObj) {
var paramsObj = paramsObj || {};
var message = paramsObj.failureMessage || "Username is not available";
var isSuccess = true;
$.post("<?php echo fURL::getDomain(); ?>/ajax/username",
function(data) {
validateStatus(data.status);
});
function validateStatus(status){
if (status === 'notavailable'){
Validate.fail("not available");
}
}
};
I've built a function for checking a username. I'm using it as a callback for form validation in CodeIgniter, and it works nicely. However, I'd like to also use it with AJAX to check on the fly if the user has JS enabled. So my controller has this:
function check_username($s = FALSE)
{
if ($s):
$this->db_common->like('username', $s);
$query = $this->db_common->get('users');
if ($query->num_rows() > 0):
$this->form_validation->set_message('check_username', 'Username taken. Choose another!');
return FALSE;
else:
return TRUE;
endif;
else:
echo 'Username required';
endif;
}
And my HTML/JS is this:
$(document).ready(function()
{
var delayed;
$("#username").keyup(function()
{
clearTimeout(delayed);
var value = this.value;
if (value)
{
delayed = setTimeout(function() {
$.ajax
({
type: "POST",
url: "<?php echo base_url(); ?>auth/check_username/",
data: $("#username").val(),
success: function(html)
{
$("#username_check").html(html);
}
});
}, 100);
}
});
});
Basically, I'm returning FALSE if the username exists and TRUE if it does exist. How do I get my jQuery AJAX to see that? Basically, I want jQuery to check if it's false, then say 'username exists' and if it's true, then 'username is okay'.
Do something like the following:
echo 'ok';
return TRUE;
The reason for this is that jQuery can't see the boolean values returned by PHP as they're not send to the browser's output.
Basically, I'm returning FALSE if the username exists and TRUE if it does exist. How do I get my jQuery AJAX to see that?
You can't directly. I would output 0 or 1 instead.
I would return true or false as JSON boolean from your PHP script and use javascript's eval() function to evaluate that to a javascript var.
There is a way to do it with PHP and jQuery. Here is an example...
simply have your php script echo back true or false.
PHP-> echo true; or echo false;
$.post("your_url/your_class/your_method", { } ,
function(data) {
if(data) alert('true');
else alert('false');
}, "json")
.error(function() { //alert("an AJAX error occurred!");
});