I'm attempting to use jQuery's remote validation method for a basic (well, should be) ajax call to some server-side logic. Now, where my situation gets peculiar is that i'm using SlimFramework and so I'm posting to a route, not a direct script page.
Here is the JS:
rules: {
email: {
required: true,
email: true,
remote: {
url: 'http://localhost:3000/email/check',
async: false,
type: 'post',
dataType: 'json',
data: {
email: function() {
return $('#email').val();
}
}
}
}
}
messages: {
email: {
required: 'Please enter an email address.',
remote: 'This email is already taken.'
}
}
Here is my server-side logic which I am almost certain is correct:
$app->post('/email/check', function() use ($app) {
$request = $app->request;
$email = $request->post('email');
$response = '';
$user = $app->user
->where('email', $email)
->first();
if($user) {
$response = false;
} else {
$response = true;
}
header("HTTP/1.1 200 OK");
header('Content-Type: application/json');
echo json_encode($response);
});
UPDATE
To be more specific, when I check the network response in the inspector, its seems the request is being made successfully:
However, The remote validation message that i specified in the messages property of the validation object is not being thrown...
Any suggestions as to why it is not functioning?
Related
I am using CodeIgniter with jQuery validation. I am using remote to check mobile number and email id is already available or not in the database. So there is no issue when the user registers. I am getting the issue on the edit page.
On the edit page, I just change the name and address but mobile number and email id both are showing already exist. I haven't change mobile and email. I know it will call the controller to check mobile and email are available or not but is there any other way to handle this issue?
I mean, not to check the previous data and check current data if the user enters anything in the field.
I want to check user against the database when creating the account, but NOT check user against the database when editing the account.
$("#edit_member").validate({
errorElement: 'div',
rules: {
name: {
required: true,
alphabets: true,
minlength: 3
},
email: {
required: true,
Email: true,
remote: {
url: baseUrl + "/AddMember/isEmail",
}
},
phone: {
required: true,
number: true,
minlength: 10,
maxlength: 10,
remote: {
url: baseUrl + "/AddMember/isMobile",
// async: false
}
},
address: {
required: true,
minlength: 10
}
},
messages: {
email: {
remote: "Email already Exists"
},
phone: {
remote: "Mobile no already Exists"
},
},
submitHandler: function(form) {//form.submit();}
});
Controller
function isEmail()
{
$email = trim($this->input->get('email'));
$result = $this->addmember_model->isEmail($email);
if($result)
{
echo $msg = "false";
}
else
{
echo $msg = "true";
}
}
function isMobile()
{
$mobile = trim($this->input->get('phone'));
$result = $this->addmember_model->isMobile($mobile);
if($result)
{
echo $msg = "false";
}
else
{
echo $msg = "true";
}
}
Model
function isEmail($email)
{
$result = $this->db->where(['email'=>$email,'is_status'=>1])
->get('members')
->row();
return $result;
}
function isMobile($mobile)
{
$result = $this->db->where(['phone'=>$mobile,'is_status'=>1])
->get('members')
->row();
return $result;
}
Use PHP to determine if the page is Editing or Creating and set a variable as such. You could look at a URL segment with the URI Class.
<?php
$create = ($this->uri->segment(3) == "create") ? TRUE : FALSE;
?>
Then use PHP to write the relevant rule(s) for that particular version of the View.
$("#edit_member").validate({
....
rules: {
....
email: {
required: true,
Email: true,
<?php if ($create) : ?>
remote: {
url: baseUrl + "/AddMember/isEmail",
}
<?php endif; ?>
},
....
The above only works when this part of the JavaScript is in the View file and not included from an external JavaScript file.
Otherwise, if .validate() is part of an externally included JavaScript file, then you can use the .rules() method instead.
After the JavaScript includes (after .validate() invoked), programmatically remove the remote rule.
<?php if ($edit) : ?>
<script>
$(document).ready(function() {
$('[name="email"]').rules('remove', 'remote');
});
</script>
<?php endif; ?>
I want to make validation on Email using jQuery
A regular validation (required) and other verification using Ajax
first function to validate if email exist and other to verify is not in black list (other table)
$('#form').validate({
errorElement: 'span',
rules:{
Email: {
required: true,
email: true,
remote: '/ifexist'
}
},
messages:{
Email:{
remote:'email already exist'
}
}
});
I try to add other remote like this, but it doesn't work
remote: '/ifexist'
remote: '/inblacklist'
My php code
if(isset($_GET['Email'])){
$is_valid = Member::inblacklist($email);
header('Content-Type: application/json');
echo json_encode($is_valid);
}else{}
Any solution ?
This answer to this question claims that the jQuery validation plugin does not support multiple remotes (I haven't seen any credible evidence to prove neither the claim nor otherwise, yet). I'd have done something as follows if I was to handle your case.
$('#form').validate({
errorElement: 'span',
rules:{
Email: {
required: true,
email: true,
remote: {
url:'/ifexist',
type:'POST', //Or whatever
data:function(){
return $("#email").val(); // The value of the email field
},
dataType:"JSON", // So that you can return a JSON object from the backend
dataFilter:function(responseData){ // Handles the response
/* Assume you return a JSON object as follows
* {"isValid":false, "reason":"blacklisted"}
* or may be
* {"isValid":false, "reason":"duplicate"}
*/
alert(responseData.reason); // Or whatever
return responseData.isValid; // validation result
}
}
}
},
// Rest of the validation logic
What happens here is that, you take control the response from the backend's validation routine and handle it as you desire.
The plugin is almost fully customizable. Refer to the documentation for futher details.
EDIT (after updates to the original question)
Backend in php may be something as follows.
if(isset($_POST['Email'])){
$email = $_POST['Email'];
$response = null;
$isInBlackList = Member::inblacklist($email);
if($isBlackList){
// User is in the blacklist
$response = array("isValid"=>false, "message"=>"This email is blacklisted!"); // Initialize $response
}
else{
$alreadyExists = Member::alreadyExists($email); // You have to implement this.
if($alreadyExists){
// Email already exists
$response = array("isValid"=>false, "message"=>"This email is already in user"); // Initialize $response
}
else{
// We found a valid email
$response = array("isValid"=>true);
}
}
header('Content-Type: application/json');
echo json_encode($response);
}else{}
Notice the usage of php array() to encapuslate the response and return that as JSON.
I need to prevent form from submitting when remote call returns true as result. How can I do this?
The JS code:
var userForm = $('#user-form');
userForm.validate({
rules : {
email : {
email: true,
remote: {
url: userForm.find('#uniqueUrl').val() + '/isUniqueEmail',
type: 'POST',
data: function(){
return $('#email').val()
},
complete: function(data){
if(data.responseText.trim() == 'true'){
return false;
}
}
}
}
}
});
Server side:
public function isUniqueEmail()
{
$result = $this->users->isUniqueEmail($this->input->post('email'));
if($result):
echo false;
else:
echo true;
endif;
}
Quote OP:
"I need to prevent form from submitting when remote call returns true as result."
That's backwards. You would return false to block the submit and trigger the validation message.
You don't need the data option since the plugin sends the field value by default. You also don't need the complete option as the plugin captures the server response automatically.
JavaScript:
var userForm = $('#user-form');
userForm.validate({
rules: {
email: {
email: true,
remote: {
url: userForm.find('#uniqueUrl').val() + '/isUniqueEmail',
type: 'POST' // default is GET
}
}
}
});
Server-side:
public function isUniqueEmail()
{
$result = $this->users->isUniqueEmail($this->input->post('email'));
if($result):
// setting message in PHP allows you to dynamically have any message
echo json_encode('name is already taken');
else:
echo true;
endif;
}
ALTERNATE
(Custom error message set in JavaScript)
JavaScript:
var userForm = $('#user-form');
userForm.validate({
rules: {
email: {
email: true,
remote: {
url: userForm.find('#uniqueUrl').val() + '/isUniqueEmail',
type: 'POST' // default is GET
}
}
},
messages: {
email: {
remote: "name is already taken"
}
}
});
Server-side:
public function isUniqueEmail()
{
$result = $this->users->isUniqueEmail($this->input->post('email'));
if($result):
echo false;
else:
echo true;
endif;
}
DOCUMENTATION: http://jqueryvalidation.org/remote-method/
I'm trying to send a form build with CodeIgniter via AJAX and trying to get the response with JSON. However, I only see the respond when I open my developer tab (I'm not even sure, if that's actually a respond since it's showing both of the json data's).
All it shows, is the loading spinner, and after that it vanishes.
Code have been tested without AJAX and it works, so there can't be errors in PHP.
Here's my controller for resetting the password:
<?php
Class Users extends CI_Controller {
public function forgot_pass()
{
if(!$this->input->post('to_email'))
{
exit("No data");
}
$this->load->model('user');
$email = $this->input->post('to_email');
$email_addr = $this->user->get_email_address($email);
if(empty($email_addr))
{
echo json_encode(array('pls'=>0, 'msg' => "E-mail address was not found. Try again"));
}
$this->load->helper('string');
$new_password = random_string('alnum', 8);
$this->load->library('phpass');
$update_password = array( 'password' => $this->phpass->hash($new_password));
$update_password = $this->user->update_password($email, $update_password);
$this->load->library('email');
$config['newline'] = '\r\n';
$this->email->initialize($config);
$this->email->from('your#example.com', 'Your Name');
$this->email->to($email);
$this->email->subject('New password');
$this->email->message("Hey, " .$email_addr['name']. ". Your new password is: " .$new_password);
if($this->email->send())
{
echo json_encode(array('pls'=>1, 'msg' => "Password has been sent to given e-mail address"));
}
}
}
?>
And here's my AJAX call written with jQuery:
$(document).ready(function() {
$("form#forget_pass_form").on('submit', function(e){
e.preventDefault();
$("#loading_spinner").show();
var from = $(this);
$.ajax({
url: from.attr('action'),
type: from.attr('method'),
data: $(from).serialize(),
}).done(function(data) {
if(data.pls == 0) {
$("#forgot-pass-success").hide();
$("#forgot-pass-error").show();
$("#forgot-pass-error").fadeIn(1000).html(data.msg);
}
if(data.pls == 1) {
$("#forgot-pass-error").hide();
$("#forgot-pass-success").show();
$("#forgot-pass-success").fadeIn(1000).html(data.msg);
}
$("#loading_spinner").hide();
});
return false;
});
});
Firstly, can you try setting the correct header in the Controller?
header('Content-Type', 'application/json');
Or better yet:
$this->output->set_content_type('application/json');
As a side note, you should make sure you are always returning JSON data, so I would remove the exit() message and put a default JSON response at the bottom of the method.
Don't forget, when you echo your JSON, you can put return; afterwards to stop any more code running afterwards in that method.
Most of your code is ok. But you need to change some lines, both in your js, and controller.
Change 1(In Ajax function)
Change your ajax function and add dataType: "json" option
$.ajax({
url: from.attr('action'),
type: from.attr('method'),
dataType: "json",
data: $(from).serialize(),
}).done(function(data) {
....
});
Change 2 (In controller)
exit("No data");
to
exit(json_encode(array('pls'=>0, 'msg' => "No data")));
Change 3 (In controller)
echo json_encode(array('pls'=>0, 'msg' => "E-mail address was not found. Try again"));
to
exit(json_encode(array('pls'=>0, 'msg' => "E-mail address was not found. Try again")));
explanation
First change tell your script to handle the response data as Json
Second change is to keep all your return type same, if not when you sending only the no data response you are not handling this option from youe js.
And the last change make sure you stop further processing when sending email fails, and stop from showing both json.
I would like to suggest you about json return.
First in your ajax you have to use dataType: 'json'
$.ajax ({
url: from.attr('action'),
type: from.attr('method'),
data: $(from).serialize(),
dataType: 'json',
}).done(function(data) {
..your code..
});
CodeIgniter have output class, why don't you use output class to respond to ajax from CI.
$output = array('pls' => 1,
'msg' => "Password has been sent to given e-mail address"
);
$this->output->set_content_type('application/json')
->set_output(json_encode($output));
Use output class, this is more efficient then echo
I hope it will helps you for better code style.
while processing a form with an Ajax call to one of my controller function then it will show a notification inside a div i need to display this notification message which already included with the design with special css format ..
i though it can be done through rendering the notifications view which i split it from the main design
i tried to do like this ..
public function add ()
{
$data = array();
if (!empty($_POST)) {
$this->model->insert();
$this->load->view('dashboard/notification', $data);
exit;
}
$this->load->view('dashboard/categories', $data, FALSE);
}
but sadly it didn't work and nothing appear ..
when i printed a simple message to show if everything working normally it shows up the message and print it normally ..
public function add ()
{
$data = array();
if (!empty($_POST)) {
$this->model->insert();
echo 'message';
exit;
}
$this->load->view('dashboard/categories', $data, FALSE);
}
and this is the jquery script
$(document).ready(function() {
$("#addCatgory").validate({
rules: {
categoryname: {
required: true,
minlength: 5
},
categoryslug: {
required: true,
minlength: 5
},
categorytype: {
required: true,
min : 1
}
},
messages:{
categoryname : 'Please enter your name',
categoryslug : 'Please enter a valid email',
categorytype : 'Please enter a valid type'
},
submitHandler: function(form) {
$(form).ajaxSubmit({
type: "POST",
async: false,
data: $("#addCatgory").serialize(),
success: function(data){
$('#result').html(data);
},
error: function(){alert('error');}
});
}
});
});
You need to modify this part by setting TRUE as third parameter so HTML is printed back to your Ajax response
public function add ()
{
$data = array();
if (!empty($_POST)) {
$this->model->insert();
echo $this->load->view('dashboard/notification', $data, TRUE);
exit;
}
$this->load->view('dashboard/categories', $data, FALSE);
}