I'm using the jquery validation plug-in. I don't have any idea how the remote function works.
So far this is my code:
functions.js
user: {
required: true,
remote: {
url: "http://localhost/iTransaction/home/checkUser",
type: "post",
async: false
}
}
Controller:
function checkUser(){
return $this->itransaction_model->checkUser();
}
Model:
function checkUser(){
$this->db->select("user");
$query = $this->db->get("member");
$row = $query->row();
echo $row->user;
if($row->user == $this->input->post("user")){
return true;
}else{
return false;
}
}
The remote is supposed to check whether the username already exists or not.
From the docs:
The serverside resource is called via jQuery.ajax (XMLHttpRequest) and gets a key/value pair corresponding to the name of the validated element and its value as a GET parameter. The response is evaluated as JSON and must be true for valid elements, and can be any false, undefined or null for invalid elements, using the default message; or a string, eg. "That name is already taken, try peter123 instead" to display as the error message.
Your controller method returns a boolean value in a way that does not makes any sense to the library and is interpreted as false. You need to return the validation result in a different way:
function checkUser(){
$this->output->set_content_type('application/json');
$this->output->set_header('Cache-Control: no-cache, must-revalidate');
$this->output->set_header('Expires: '.date('r', time()+(86400*365)));
$output = json_encode(
$this->itransaction_model->checkUser() ? true : 'That username is alreay in use'
);
$this->output->set_output($output);
}
Related
I'm new at Laravel and I'm actively trying to code better, but I'm currently stuck with problems I don't know how to solve.
The controller :
public function sendGiving($contents){
$redirectURL = $contents->redirectURL;
var_dump($redirectURL); // the variable is available, logged in network section
return View::make('giving/giving')->with('redirectURL', $redirectURL);
}
The view (on AJAX) :
function submitForm() {
if (is_personal_data_complete() == true && is_offering_filled() == true && isreCaptchaChecked() == true) {
var base_url = window.location.origin;
//send ajax request
$.post("{{ route('send_giving') }}",
{
_method: 'POST',
_token: '{{ csrf_token() }}',
name: $('#txtName').val(),
email: $('#txtEmail').val(),
phone_number: $('#txtnohp').val(),
thanksgiving_offerings: total_thanksgiving,
tithe_offerings: total_tithe,
firstborn_offerings: total_firstborn,
build_offerings: total_build,
deacon_offerings: total_deacon,
mission_offerings: total_mission,
paud_offerings: total_paud,
dataType: "jsonp",
async : false,
success: function($redirectURL){
alert($redirectURL);
},
});
}
else if (is_personal_data_complete() == false) {
alert("Please fill in your data form");
}
else if (is_offering_filled() == false) {
alert("Please fill in your offerings");
}
else if (isreCaptchaChecked() == false){
alert("Please check the captcha");
}
return false;
}
The alert always returns undefined though, what am I missing?
Please try this:
return response()->json($redirectURL)
When you use Laravel and write API, you need to use this command to reponse JSON for frontend
The view() function just creates an instance of the View class. Not just an HTML string. For that you should call render():
$returnHTML = view('giving/giving')->with('redirectURL', $redirectURL)->render();
return response()->json(array('success' => true, 'html'=>$returnHTML));
When you return in your controller return View::make('giving/giving')->with('redirectURL', $redirectURL);
You are returning a VIEW file, which will be return as the body of the HTTP request.
and you are also passing to Your view file redirectUrl which will be accessible in your view file.
And when you perform your AJAX request, you are getting a response with a body which contain HTML/TEXT Content not JSON.
SO YOU CAN'T HAVE ACCESS TO redirectURL VARIABLE
So what you should do by the way is to return simple a JSON body by returning in your Controller something like
return response()->json([
'redirectURL' => $redirectURL
]);
No need to return a VIEW FILE
You can't return in the same controller JSON data in the body and a VIEW FILE
The main issue is here that you try to send a POST with JSONP data type.
There are a lot of explanations on this on SO, e.g https://stackoverflow.com/a/18934048/8574551
Try to remove it and use smth like the next:
...
contentType: "application/json",
dataType: "json",
...
On another hand, you can omit these 2 parameters (check https://api.jquery.com/jquery.post/)
To return the data from the controller action you can use response()->json(..) (as described in other answers)
the problem is on the ajax request, as after changing the format it works nicely
I am using jquery validation to double-check entered values. This is working find as long as my controller return true or false. Now I would like to analyze the return value first and then decide if the value is correct or incorrect.
So I am running the remote function like this:
supervisor: {
required:true,
remote: function() {
return {
url: "getADobject/" + $('#supervisor').val(),
data: '',
complete: function(data) {
console.info(data);
$(".loading").css('visibility', 'hidden');
if(data.responseJSON === false){
console.info(data.responseJSON);
//$('#supervisor').validate() = false;
//return 'false';
}
}
}
The object data returns the correct information and I also can do an if statement. But now I would like to say, yes the validation is OK or not. Can someone tell me how to add this information? I tried it already with an easy return true / 'true' / $valid = true but nothing :(
Thanks in advance
Stephan
I made an ajax request to the server for checking whether a particular username exists in the database. Here is the code for that..
$("input[placeholder='Username']").focusout(function() {
var username = $("input[placeholder='Username']").val();
if(username.length <3 || username.length>20) {
$("#username_taken").html("Username must be between 3-20 characters!");
usernameFlag = true;
}
else if(username != null) {
$.ajax({
type: "POST",
url: "/data/validate_username",
data: username,
success: function(isValid) {
if(!isValid) {
$("#username_taken").html("The username has already been taken!");
usernameFlag = true;
}
},
error: function() {
$("#username_taken").html("Could not verify username from server!");
}
});
}
});
In the server side I have written a RestController to handle this request and provide the data on whether the user exists or not.
// necessary imports done...
#RequestMapping("/data")
#RestController
public class UserAccountRest {
#Autowired
private UserAccountService userAccountService;
#PostMapping("/validate_username")
public boolean validateUsername(String username) {
return !userAccountService.accountExists(new UserAccount(username));
}
}
Normally spring auto populates the parameters like username, if it was a form submit. But here status 500 Internal Server Error occurs, and in the console it says that the id must not be null. This means that the username is not populated.
I could probably use HttpRequest object in the parameter and get the username from it. But is there any way to configure so that the username is directly populated?
The data sent needs to have key/value pairs.
When you get the value of an <input> you only have 1/2 of the pair. Your variable username only contains the value part
Change
data: username,
To
data: {username : username}
Have you tried doing
public boolean validateUsername(#RequestBody String username) {
return !userAccountService.accountExists(new UserAccount(username));
}
You are probably posting a JSON value which should be a key value pair.
Good day guys. In my laravel application I'm trying to check if attendence for a particular date, subject, grade exists in my table. If so I have an if statement setup to display desire results based on what is returned.
I'm making the request with ajax but it seems like ajax keeps running the error function and I don't seem to get any error code whatsoever or internal server error(500, 404, 403, etc) In my console the status return is 200 ok
here is my script:
$(document).on('change', '#subject', function(event) {
event.preventDefault();
/* Act on the event */
var subject = $('#subject').val();
var grade = $('#grade').val();
var date = $('#date').val();
if (subject != "" && grade != "") {
$.ajax({
url:"/attendence/students",
method:"GET",
data:{"subject_id":subject, "grade_id":grade, "date":date},
dataType:"json",
success:function(data){
$("#result").html(data);
},
error:function(){
$("#result").html('There was an error please contact administrator');
}
});
}
});
Here is the controller the request is send to:
public function students(Request $request)
{
//
$grade = Grade::findOrFail($request->grade_id);
$subject = Subject::findOrFail($request->subject_id);
$students = Student::where('grade_id', $grade->id)->get(['id', 'first_name','middle_name', 'surname', 'grade_id']);
$statuses = Attendence::statuses();
// this check if attendence has been setup for the given date.
// if so prevent user for enter another date
$attendenceExists = Attendence::where([
'grade_id' => $grade->id,
'subject_id' => $subject->id,
'date' => $request->date
])->first();
if ($attendenceExists) {
return response()->json('A recorded attendence already exists for the seleced grade and subject!');
}
else {
return \View::make('attendence.partials.attendence-form')->with(array(
'students' => $students,
'subject' => $subject,
'date' => $request->date,
'statuses' => $statuses
));
}
}
Now, if this code returns true:
// this check if attendence has been setup for the given date.
// if so prevent user for enter another date
$attendenceExists = Attendence::where([
'grade_id' => $grade->id,
'subject_id' => $subject->id,
'date' => $request->date
])->first();
if ($attendenceExists) {
return response()->json('A recorded attendence already exists for the seleced grade and subject!');
}
The condition here runs and the right result is returned. But my else statement in the above does run but I don't get the right result. This is the result I get:
There was an error please contact administrator
Which shows that it is this part of the ajax request that is running:
error:function(){
$("#result").html('There was an error please contact administrator');
}
Surprisingly when I check the console this is what I see:
Which is exactly what I want but ajax is return otherwise. Am I doing something wrong?
Your dataType is set to json while you're returning html. Change it to html.
$.ajax({
url:"/attendence/students",
method:"GET",
data:{"subject_id":subject, "grade_id":grade, "date":date},
dataType:"json",
statusCode: {
200: function(data) {
$("#result").html(data.responseText);
};
}
}
});
Try this. I hope this will help you
I would say don't set the dataType at all. Just remove that setting altogether and let the jQuery ajax() method detect it automatically for you. That way, if the response type is JSON, it'll work. If the response type is HTML, it'll also work. 👍🏻
I read your reply regarding the jQuery validator where you outline a method to check a username against a value in a database.
Ive tried implementing this method but no matter what is returned from the PHP file I always get the message that the username is already taken.
Here is ths custom method...
$.validator.addMethod("uniqueUserName", function(value, element) {
$.ajax({
type: "POST",
url: "php/get_save_status.php",
data: "checkUsername="+value,
dataType:"html",
success: function(msg)
{
// if the user exists, it returns a string "true"
if(msg == "true")
return false; // already exists
return true; // username is free to use
}
})}, "Username is Already Taken");
And here is the validate code...
username: {
required: true,
uniqueUserName: true
},
Is there a specific way i am supposed to return the message from php.
Thanks
A
For anyone else who stumbles upon this, validate supports 'remote' method, which may not have existed in 2010:
https://jqueryvalidation.org/remote-method/
$("#myform").validate({
rules: {
email: {
required: true,
email: true,
remote: {
url: "check-email.php",
type: "post",
data: {
username: function() {
return $("#username").val();
}
}
}
}
}
});
You are doing an AJAX request, ergo: the validation is already finished working when your custom validator returns either true or false.
You will need to work with async. See also this post: How can I get jQuery to perform a synchronous, rather than asynchronous, Ajax request?
Something like:
function myValidator() {
var isSuccess = false;
$.ajax({ url: "",
data: {},
async: false,
success:
function(msg) { isSuccess = msg === "true" ? true : false }
});
return isSuccess;
}
Warning:
As of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is
deprecated; you must use the success/error/complete callback options
instead of the corresponding methods of the jqXHR object such as
jqXHR.done() or the deprecated jqXHR.success().
It took me forever to figure out how to get a jsonified string containing the value of an element in the page into the remote request- this is the result of a combination of many hours and trying many search results.
Key points:
async:false has been deprecated,
the function call right after remote: is the key for creating the data string with the element's value. Trying to access a current value from the form after data: was returning a blank value for the field with dataType set as json.
$("#EmailAddress").rules("add", {
required: true,
remote: function () { // the function allows the creation of the data string
// outside of the remote call itself, which would not
// return a current value from the form.
var emailData = "{'address':'" +
$('#SignupForm :input[id$="EmailAddress"]').val() +
"'}";
var r = {
url: "foobar.aspx/IsEmailAvailable",
type: "post",
dataType: "json",
contentType: "application/json; charset=utf-8",
cache: false,
data: emailData,
dataFilter: function(response) {
this.email_run = true; //fix for race condition with next button
return isAvailable(data); //return true or false
}
};
return r;
},
messages: {
remote: "* Email in use"
}
});
.ASPX page:
<input id="EmailAddress" required name="Email" type="email" placeholder="Email Address*" runat="server"/>
C# Code Behind:
[WebMethod]
public static object IsEmailAvailable(string address){...}
Formatting the response object:
function isAvailable(data) {
var response = JSON.parse(getJsonObject(data));
return (response.isAvailable === "True") ? true : false;
};
//transform response string to a JavaScript Object()
//http://encosia.com/never-worry-about-asp-net-ajaxs-d-again/
function getJsonObject(data) {
var msg = eval('(' + data + ')');
if (msg.hasOwnProperty('d'))
return msg.d;
else
return msg;
};
Here's my "old school" hack...
Below a utility function that allows the use of "asynchronous" validations with "jquery.validate.js" library. This function creates a delay between user keystrokes otherwise the validation function "validFunc" will be called "all time" which is not very performative in some circumstances and especially problematic for functions that perform validations on "serverside"/"backend" (ajax calls basically). In this way the "validFunc" validation function is only called when the user stops typing for a certain period of time which also allows a "realtime" validation ("onkeyup": true on jqv settings) as it occurs while the user is typing.
IMPORTANT: Validations involving the use of the "jqvAsyncValid" function should always be the last ones to avoid conflicts with the others due to the asynchrony.
{
[...]
"rules": {
"field_name": {
"required": true,
"maxlength": 12,
"minlength": 4,
// NOTE: Validation involving the use of the "jqvAsyncValid" function. By Questor
"my_custom_ajax_validation": true
},
[...]
}
ANSWER'S CODE:
// NOTE: Adds the custom validation "my_custom_ajax_validation". By Questor
$.validator.addMethod("my_custom_ajax_validation", function (value, element) {
return jqvAsyncValid(element, "my_custom_ajax_validation", myValidationFunc, this);
}, "My error message!");
// NOTE: My validation function. By Questor
function myValidationFunc(domElement) {
if (someFuncWithAjaxCall(domElement.value) == "ALL_RIGHT!") {
return true;
} else {
return false;
}
}
// NOTE: Global "json" variable that stores the "status" ("isValid") and cycle control
// ("toCtrl") of asynchronously validated elements using the "jqvAsyncValid" function.
// By Questor
var jqvAsyncVState = {};
// NOTE: A utility function that allows the use of asynchronous validations with
// "jquery.validate.js". This function creates a delay between one user keystroke and
// another otherwise the validation function "validFunc" will be called "all time"
// which is not very performative in some circumstances and especially problematic
// for functions that perform validations on the serverside/backend (ajax calls basically).
// In this way the "validFunc" validation function is only called when the user stops
// typing for a certain period of time, which also allows a "realtime" validation
// as it occurs while the user is typing. By Questor
// [Ref .: https://jqueryvalidation.org/ ]
//. domElement - DOM element informed by jqv in the "addMethod" for the anonymous
// function;
//. asyncRuleNm - Validation name added via "addMethod";
//. validFunc - Function that will do the validation. Must have the signature
// "funcName(domElement)" returning "true" for valid and "false" for not;
//. jQValidInst - Instance of the current jqv within "addMethod". It is usually
// denoted by "this";
//. toInMsecs - "Timeout" in "milliseconds". If not informed the default will be
// 1500 milliseconds. Be careful not to use a very short timeout especially in
// "ajax" calls so as not to overload the serverside/backend.
// Eg.: `return jqvAsyncValid(element, "my_custom_ajax_validation", myValidationFunc, this);`.
function jqvAsyncValid(domElement, asyncRuleNm, validFunc, jQValidInst, toInMsecs) {
if (typeof toInMsecs === "undefined" || toInMsecs === "") {
toInMsecs = 1500;
}
var domEKey = jQValidInst.currentForm.id + domElement.name;
// NOTE: The validation messages need to be "displayed" and "hidden" manually
// as they are displayed asynchronously. By Questor
function errMsgHandler() {
if (jqvAsyncVState[domEKey]["isValid"]) {
// NOTE: If the current error message displayed on the element was that
// set in the rule added via "addMethod" then it should be removed since
// the element is valid. By Questor
// [Ref.: https://stackoverflow.com/a/11652922/3223785 ,
// https://stackoverflow.com/a/11952571/3223785 ]
if (jQValidInst.errorMap[domElement.name] == $.validator.messages[asyncRuleNm]) {
var iMsgNow = {};
iMsgNow[domElement.name] = "";
jQValidInst.showErrors(iMsgNow);
}
} else {
var iMsgNow = {};
// NOTE: If the element is invalid, get the message set by "addMethod"
// for current rule in "$.validator.messages" and show it. By Questor
iMsgNow[domElement.name] = $.validator.messages[asyncRuleNm];
jQValidInst.showErrors(iMsgNow);
}
}
if (!jqvAsyncVState.hasOwnProperty(domEKey)) {
// NOTE: Set the global json variable "jqvAsyncVState" the control attributes
// for the element to be asynchronously validated if it has not already been
// set. The key "domEKey" is formed by the "id" of the "form" that contains
// the element and the element's "name". By Questor
jqvAsyncVState[domEKey] = {
"toCtrl": null,
"isValid": undefined
};
}
var useOnKeyup = true;
// NOTE: The "onblur" event is required for "first validation" that only occurs
// in a "blur" event - this is inherent to jqv - and for situations where the
// user types very fast and triggers "tab" and the event "onkeyup" can not deal
// with it. By Questor
domElement.onblur = function (e) {
jqvAsyncVState[domEKey]["isValid"] = validFunc(domElement);
errMsgHandler();
useOnKeyup = false;
}
if (useOnKeyup) {
// NOTE: The strategy with the event "onkeyup" below was created to create
// a "delay" between a "keystroke" and another one otherwise the validation
// function "validFunc" will be called "all time" which is not very performative
// in some circumstances and especially problematic for functions that perform
// serverside/backend validations (ajax calls basically). In this way the
// "validFunc" validation function is only called when the user stops typing
// for a certain period of time ("toInMsecs"). By Questor
domElement.onkeyup = function (e) {
// NOTE: Clear the "toCtrl" if it has already been set. This will
// prevent the previous task from executing if it has been less than
// "toInMsecs". By Questor
clearTimeout(jqvAsyncVState[domEKey]["toCtrl"]);
// NOTE: Make a new "toCtrl" set to go off in "toInMsecs" ms. By Questor
jqvAsyncVState[domEKey]["toCtrl"] = setTimeout(function () {
jqvAsyncVState[domEKey]["isValid"] = validFunc(domElement);
errMsgHandler();
}, toInMsecs);
};
}
return jqvAsyncVState[domEKey]["isValid"];
}