I have a problem with Jquery form validation.
I have this script:
$(document).ready(function () {
var validateUsername = $('.info');
$('#username').blur(function () {
var t = this;
if (this.value != this.lastValue) {
if (this.timer) clearTimeout(this.timer);
validateUsername.removeClass();
validateUsername.addClass('info');
validateUsername.html('<img src="images/load.gif" height="16" width="16" /> checking availability...');
this.timer = setTimeout(function () {
$.ajax({
async: false,
cache: false,
url: 'process.php',
data: 'action=validateusername&username=' + t.value,
dataType: 'json',
type: 'post',
success: function (j) {
validateUsername.removeClass();
validateUsername.addClass(j.class);
validateUsername.html(j.msg);
}
});
}, 500);
this.lastValue = this.value;
}
})
});
and in php something like this :
public static function validateUserName($username) {
$username = trim($username); // remove white spacing
$response = array(); // define response array
if(!$username) { // check if not empty
$response = array(
"ok" => false,
"class" => "error",
"msg" => "Please specify your username");
} elseif (strlen($username)<5) { // check the lenght
$response = array(
"ok" => false,
"class" => "error",
"msg" => "UserName must be at least 5 characters long");
} elseif (!preg_match('/^[a-zA-Z0-9.\-_]+$/',$username)) { // check the pattern
$response = array(
"ok" => false,
"class" => "error",
"msg" => "Your username can contain only Aplhanumerics, dash, underscore and period");
} elseif (!self::userNameAvailable($username)) { // check availability
$response = array(
"ok" => false,
"class" => "error",
"msg" => "UserName already taken !");
} else { // everything good
$response = array(
"ok" => true,
"class" => "success",
"msg" => "This username is free");
}
return $response;
}
As you can see php returns 3 fields of data....
problem is the user can still send the form even when php returns "false" and i have no idea how to fix it.
I could just let the form to be sent a do one more validating purely with php,
but what is the point of using ajax then.
I´d be very thankful if somebody could help me.
Why do you validate every 500ms and not on form submit or input change?
General pattern for form validation using jQuery is to validate on form's submit() event, like:
$('form').submit(function () {
...
(validation code here)
...
});
If validation doesn't succeed, you can just return false from submit() to avoid submitting the form.
Also note that you need to do server-side validation of posted data, too, as jQuery validation can be fooled easily.
I think a simple solution is to set a global variable:
var validform = false;
And check it in form submit event :
$("#myform").submit(function(){
return validform;
});
Now you can set it as TRUE or FALSE on your AJAX callback.
$.ajax({
// Whatever',
success: function (j) {
validform = true;
}
});
you can do a little more customization too.
Related
I have a form that I'm trying to validate with jquery validation plugin and codeigniter 4, I have enabled csrf that set to auto generate for every request. I'm able get validation status on first request but when I try another request I get error 403, and when I set second param to json_encode() I get error 500. I want to be able to update csrf after each request on ajax call.
//My router
$routes->post('check-category', 'Admin\Category::check_category');
//my controller
//check if category name exist
public function check_category()
{
$name = $this->request->getPost('name');
$query = $this->db->table('categories')
->where(['cat_name' => $name])
->get()
->getResult();
$status = true;
if(count($query) > 1){
$status = false;
}else{
$status = true;
}
$data['csrf'] = csrf_hash();
echo json_encode($status, $data);
}
// javascript
$('#create_category').validate({
onkeyup: false,
rules: {
name: {
remote: {
url: 'check-category',
type: "post",
data:{
csrf_hash_name: function(){
return $('input[name="csrf_hash_name"]').val();
}
},
complete: function(data){
$('input[name="csrf_hash_name"]').val(data.csrf);
}
}
}
},
messages: {
name: {remote: "This category exists."}
},
submitHandler: function(form) { return false; }
});
Thanks in advance.
the structure of the php function json_encode() looks like this:
json_encode ( mixed $value , int $flags = 0 , int $depth = 512 ) : string|false
and returns:
a string containing the JSON representation of the supplied value.
in your controller function check_category() you are sending $status, while $data is setting an invalid flag:
echo json_encode($status, $data); // wrong
change $status = true; into $data['status'] = true;
and just echo both, status and the csrf hash
echo json_encode($data); // correct
After so much struggle I finally found the solution of my problem. Now I'm able to update csrf token with the dataFilter object and get rid off error 403 during ajax call.
Here is what I have done to my controller even I broked Mvc principle by getting data from db direct to the controller.
I know it could not the best way for what I have done, Please correct me if any suggestion I'll appreciate. Thanks!
//my controller method
public function check_category()
{
$name = $this->request->getPost('name');
$query = $this->db->table('categories')->where(['cat_name' => $name])->countAllResults();
$valid = true;
if($query > 0){
$valid = false;
}else{
$valid = true;
}
$csrf = csrf_hash();
return $this->response->setJSON(['valid'=>$valid, 'csrf'=>$csrf]);
}
// my javascript
$('#create_category').validate({
onkeyup: false,
rules: {
name: {
required: true,
remote: {
url: 'check-category',
type: 'post',
dataType:'json',
dataFilter: function(data){
let obj = eval('('+data+')');
$('input[name="csrf_hash_name"]').val(obj.csrf);
return obj.valid;
},
data:{ csrf_hash_name: function(){ return $('input[name="csrf_hash_name"]').val(); } }
}
}
},
messages: {
name: {
required: "Enter a Category.",
remote: "{0} This category exists."
}
},
submitHandler: function(form) {
return false;
}
});
Let's say I have a login form, with 2 fields, email and password, first I want to check if the user email is actually registered or not, so I made a separate file named user_check.php with the PHP code to check if a user exists or not,
include_once('../../classes/user.class.php');
$User = new User();
if ($User -> UserExists($_POST['login_email']) === true) {
echo true;
} else {
echo false;
}
now from login page, I want to call in an AJAX request to actually check if the UserExists() method returns false or true, if it returns false I will just give an error message to the user, else the code will continue
$.ajax({
url: 'ajax/login-handler/user_check.php',
type: 'POST',
data: {login_email: email.val()},
cache: false,
success: function(data) {
if (data == 1) {
alert('Exists');
} else alert('Doesn\'t Exist');
}
});
Should I do nested Ajax calls for other database checks inside success block if statements? Or if I need to do separate Ajax calls how can I pass one Ajax calls response to the other call?
If you have to make multiple asynchronous calls, I think the cleanest way would be to have an async function that awaits every asynchronous call you have to make. For example, using fetch, which supports well-formed Promises:
$(form).on('submit', (e) => {
e.preventDefault();
tryLogin()
.catch((e) => {
// handle errors
});
});
const tryLogin = async () => {
const userExists = await fetch('ajax/login-handler/user_check.php', {
method: 'POST',
body: JSON.stringify({ login_email: email.val() })
});
if (!userExists) {
// doesn't exist, tell user and return
return;
}
// user exists
const someOtherResult = await fetch('ajax/login-handler/somethingElse.php', {
method: 'POST',
body: JSON.stringify({ foo: 'bar' })
});
// do stuff with someOtherResult
};
First create your login page, then create your username and password field. And put this code after the JQuery library.
$(document).ready(function(){
$('#login').click(function(){
var usernameAdmin = document.getElementById("username").value;
var password = document.getElementById("password").value;
var dataString = 'usernameAdmin='+usernameAdmin+'&password='+password;
$.ajax({
type: "POST",
url: "controler/login.php",
data: dataString,
cache: false,
success: function(data)
{
document.getElementById("login").disabled = false;
window.location="admin/";
}
});
});
});
Now create your Ajax file according to the code below and enjoy it
if(isset($_POST['usernameAdmin']))
{
$username = $_POST['usernameAdmin'];
$password = $_POST['password'];
$c = $check->check_login_admin($username,$password);
if($c == true)
{
echo 1;
}
else
{
echo 0;
}
}
protected function check_login_admin($username,$password)
{
parent::__construct();
$sql = $this->_SELECT." `users` WHERE username=:u AND password=:p";
$r = $this->_DB->prepare($sql);
$r->bindValue(':u', $u);
$r->bindValue(':p', $p);
$r->execute();
$c = $r->rowCount();
if($c == 1)
{
foreach($r->fetchAll() as $row);
$_SESSION['log_true_admin']= true;
$_SESSION['name']= $row['name']." ".$row['family'];
$_SESSION['id']= $row['id'];
return true;
}
else return false;
}
good luck my friend
Problem: How do I validate the form and return the validation messages in modal box without refreshing the page.
I just started learning Symfony 3 and I got trouble adding data using AJAX.
I know how to include the template form inside of the modal box but I don't know how to show the error messages of $form->isValid() inside the modal and persist it.
new.html.twig
UPDATE: I can now call the method action in Controller. But when I validate the form I haven't received any validation error inside modal box.
<script>
$(function () {
$('.withdropdown').dropdown();
$('.add-company-launch').modal();
$('#company-form').submit(function(e) {
var formUrl = "{{ path('monteal_backend_company_ajax') }}";
var formData = new FormData(this)
$.ajax({
url: formUrl,
type: 'POST',
data: formData,
contentType: false,
cache: false,
processData: false,
success: function(data, textStatus, jqXHR)
{
if(data['status'] === 'success'){
alert('success');
} else {
$('#add-company').html(data['html']);
}
},
error: function(jqXHR, textStatus, errorThrown)
{
}
});
e.preventDefault();
});
})
</script>
{% endblock %}
CompanyController.php
UPDATE: I have create two methods for AJAX,
1. Method to handle a form.
2. AjaxHandler.
public function newAction() {
$company = new Company();
$form = $this->createForm(CompanyForm::class, $company);
return $this->render('Admin/Backend/Company/new.html.twig', array(
'form'=>$form->createView()
));
}
public function ajaxAction(Request $request) {
if (!$request->isXmlHttpRequest()) {
return new JsonResponse(array('message' => 'You can access this only using Ajax!'), 400);
}
$company = new Company();
$form = $this->createForm(CompanyForm::class, $company);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($company);
$em->flush();
return new JsonResponse(array(
'status' => 'success'), 200
);
}
$html = $this->renderView("Admin/Backend/Company/new.html.twig", array(
'form' => $form->createView())
);
return new JsonResponse(['status' => 'error', 'html' => $html]);
}
1 - In your newAction, just create the form and pass the view (createView) to your template.
2 - write a ajaxFormHandlerAction and here create the form, handle it, validate it, render a view in a variable :
$html = $this->renderView('yourTemplate.html.twig', array($form->createView()));
Edit: of course your ajax must post the form to your newly ajax url... END Edit
3 - if it is'nt validated
Return a JsonResponse(array('html' => $html, 'status' => 'error'));
if validated
Return a JsonResponse(array('status' => 'success'));
4 - In your ajax success callback, render the newly form if status error..
if status success, redirect or whatever
Hope this help
Edit :
something like this for your controler :
use Symfony\Component\HttpFoundation\JsonResponse;
public function ajaxFormHandlerAction(Request $request)
{
$company = getYourCompany(); //get it from db?
$form = $this->createForm(CompanyForm::class, $company));
$form ->handleRequest($request);
if($form ->isValid()){
//do whatever you want, maybe persist, flush()
return new JsonResponse(array(
'status' => 'success'));
}
$html = $this->renderView("yourModalTemplate.html.twig", array('form' => $form->createView()));
return new JsonResponse(['status' => 'error', 'html' => $html]);
}
And in your success ajax callback:
success: function(data, textStatus, jqXHR)
{
if(data['status'] === 'success'){
alert('success');
// maybe redirect the user ???
}else if(data['status' === 'error']){
$('#idOfYourModal').html(data['html']); //assuming you use jquery, or translate to javascript
}
},
You have to create a twig template with only the modal inside...
I have editable html table of user Information. There are some columns such as user_ID, branch_ID etc. when I am going to change the branch_ID of the user I want to check the particular user has tasked assigned to him or not. If he has tasks then update is not allowed. for that I am using the following java script part.
if(field=='branch_ID'){
$.ajax({
type: 'post',
url: 'check_user.php',
data: {udata: user_id},
success: function (data) {
// message_status.text(data);
}
})
}
In check_user.php
$user_id= $_POST['udata'];
$sql1="SELECT * FROM assign_task WHERE user_ID=$user_id";
$query1=mysqli_query($con,$sql1);
if(mysqli_num_rows($query1)>0){
echo"you can't update";
return false;
}
else{
echo"ok with it".$sql1;
}
The thing is I want the respond from check_user.php as an alert and return false to stop updating the content. As I am new to jQuery please help me.
You can use JSON to pass more complex data:
PHP :
if(mysqli_num_rows($query1)>0){
echo json_encode(array("success" => false));
}
else{
echo json_encode(array("success" => true,
"message" => "ok with it".$sql1));
}
Javascript:
success: function (data) {
var jsonData = JSON.parse(data);
if(jsonData.success){
alert(jsonData.message);
}
}
Remember to do more advanced checking on your variables and types first!
I am using ajax to make validation of login. I am having a problem with javascript e.preventeDefault(), when use it prevents submit and always shows validation empty field. When remove it is right but echo json data and doesnt shows validation messages inside dialog box, instead it redirects to url and echo the right json message. I think e.preventDefault prevents submit, is there any other way to put validation message inside dialog box insted of e.preventDefault() ?
$('#login_form').on('submit', function(e) {
e.preventDefault();
var username = $('#login_form input[name=sign_in_username]').val();
var password = $('#login_form input[name=sign_in_pass]').val();
$.ajax({
url: "login.php",
type: "POST",
data: {username: username,
password: password
},
dataType: 'json',
success: function(response) {
if(response.status){
$(this).unbind('submit').submit()
console.log(response);
window.location = response.url;
}
else{
$('#invalid_content').html(response.msg);
}
}
});
});
login.php
if (((!isset($_POST["sign_in_pass"]) || !isset($_POST["sign_in_username"]) ) || trim($_POST["sign_in_pass"]) == "" || trim($_POST["sign_in_username"]) == "")) {
echo json_encode(array('msg' => "Username or password are empty.", 'url' => "", 'status' => false));
exit();
}
$rows = query("SELECT * FROM customers WHERE username = ?", $_POST["sign_in_username"]);
// nese form eshte bere submit
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (count($rows) == 1) {
$row = $rows[0];
if (crypt($_POST["sign_in_pass"], $row["hash"]) == $row["hash"]) {
$_SESSION["id"] = $row["id"];
echo json_encode(array('msg' => "Success.", 'url' => "index.php", 'status' => true));
}
} else {
echo json_encode(array('msg' => "Username or password invalid.", 'url' => "", 'status' => false));
}
} else {
echo json_encode(array('msg' => "Username or password invalid.", 'url' => "", 'status' => false));
}
Your problem is not the e.preventDefault(). Your fields just don't match up, which is why they're empty.
Your data parameter should be: data: {sign_in_username: username, sign_in_password: password}.
The request your PHP script receives has the wrong field names in it.
In the future, for debugging purposes, on your PHP script, try var_dump($_POST);. This will give you an idea of what the request you received had in it.