I can't seem to get the AJAX call correct. There have been other QA that deal with the $.ajax() function but I'm trying to solve this with $.post().
When the form button is clicked the javascript at the head is executed, which includes a $.post(). The url /login is routed through and passed to loginPost function. There a response is determined and sent back to the javascript (right?). Instead, webpage renders the response (pass || fail).
Why isn't the response from the AJAX call being sent back to get processed?
This is a simple example that I am working with to get me better acquainted to how AJAX in expressJS and jQuery work. Any Help is greatly appreciated!
--views/login.jade
script(src='/_js/jquery-1.8.2.min.js')
script
$(document).ready(function(req, res) {
$('#login').submit(function() {
var formData = $(this).serialize();
console.log(formData);
$.post('/login', formdata, processData).error('ouch');
function processData(data, status) {
console.log(status);
console.log(data);
if (data == 'pass') {
$('#content').html('<p>You have successfully loggin in!</p>');
} else {
if (! $('#fail').length) {
$('#formFrame').prepend('<p id="fail">Incorrect login information. Please try again)</p>');
}
}
} //end processData
}); //end submit
}); //end ready
div.main
h1= title
div#formFrame
form(id='login', action='/login', method='POST')
p
label(for='username') Username:
input(id='username', type='text', name='username')
p
label(for='password') Password:
input(id='password', type='password', name='password')
p
input(id='button', type='submit', name='button', value='Submit')
--routes/index.js
app.post('/login', loginPost);
--routes/loginPost
module.exports.loginPost = function(req, res) {
var password = 'admin'
, username = 'user'
, data = req.body;
if (data.username == username && data.password == password) {
res.send('pass');
} else {
res.send('fail');
}
};
You still have to stop the <form> from submitting via its default action, which can be done with event.preventDefault():
$('#login').submit(function(evt) {
evt.preventDefault();
// ...
});
Otherwise, the <form> will redirect the page to its action (or back to the current address if no action was given), interrupting the $.post request.
Related
This time I want to use res.render to display html as success of DB update. I did it several times, but this time it doesn't work. It's not render html file, just displayed on chrome's console.
I think it caused because of async problem or duplicated response. I tried to many ways but I couldn't solve it, so pointers appreciated.
The code is related when the user paid service, increase user's level.
Get Access Token => Validate => res.render
app.post('/payment/validate', function(req, res, next){
// Get access token
request.post({
url : 'https://payment-company/get/token'
}, function(err, response, body) {
if(!err & response.statusCode == 200) {
var result = JSON.parse(body);
var accessToken = result.response.access_token;
// Validate payment (compare paid and would be paid)
request.get({
headers : { 'Authorization' : accessToken }
url : 'https://payment-company/find/paymentid'
}, function (err, response, body) {
if (!err && response.statusCode == 200){
var result = JSON.parse(body);
if (result.response.amount == req.body.price){
Members.findOne({id : req.user.id}, function(err, member){
// If no problem, update user level
member.level = 2;
member.save(function(err, result){
if (err) return next();
res.render('payment.view.result.ejs',
{
title : 'Success !',
description : 'level up.'
});
});
});
}
} else {
...
}
});
}
})
});
sorry to verbose code I tried to shorten code, No problem until res.render, res.render will work but it's not display page instead it just send html code to chrome's console.
Looks like there's a bit of a misunderstanding of how these requests work. What I think you intend:
Browser makes a GET request, server responds with an HTML document, the browser renders it
User takes an action
Browser makes a POST request, server responds with an HTML document, the browser renders it
What you've started coded on the frontend is an alternate method:
You make a POST request via AJAX, server responds with some JSON, you modify the current document with JavaScript to let the user know
I have registration form and i have created three function in jquery
First one is validate the form.
Second one is for checking the email uniqueness with ajax request.
Third one is for creating user this also with ajax request.
My flow on submit event is that first i am calling validation function and then on the response of that function i calling the function to check the email uniqueness on the response of this a an ajax request is done to create a user.
First one is validate the form.
function validateregForm()
{
if($('#u_name').val()=="" || !IsEmail($('#u_email').val()) || $('#u_pwd').val().length<6 || $('#c_pwd').val()!=$('#u_pwd').val())
{
if($('#u_name').val()=="")
{
$('#reg_error1').show();
}
if(!IsEmail($('#u_email').val()))
{
$('#email_msg').remove();
$('#reg_error2').show();
}
if($('#u_pwd').val().length<6)
{
$('#reg_error3').show();
}
if($('#u_pwd').val()!=$('#c_pwd').val())
{
$('#reg_error4').show();
}
return false;
}
else
{
return true ;
}
Second one is for checking the email uniqueness with ajax request.
function chkmail(email) {
var posting=$.post('http://localhost/tv100.info/index.php/user/chkmail',{u_email:$('#u_email').val()});
posting.done(function(data){
if(data=='success')
{
$('#email_error').css('display','none');
$('#email_msg').css('display','block');
return true;
}
if(data=='failure')
{
$('#email_msg').css('display','none');
$('#email_error').css('display','block');
return false;
}
});
}
Third one is for creating user this also with ajax request.
$('#regform').submit(function(event) {
var res=validateregForm()
event.preventDefault();
if(res)
{
var email=chkmail();
}
if(email)
{
$('#loading2').show();
var posting=$.post('http://localhost/tv100.info/index.php/user/create_user',$("#regform").serialize());
posting.done(function(data)
{
$('#loading2').hide();
if(data=="success")
{
$('#reg_panel').append('<span id="reg_msg">Registration successful Now You are logged IN</span>');
$('#overlay').fadeOut(300);
$('#login').html('Logout');
$('#sign_in').hide();
$('#cmmnt_field').show();
}
if(data=="failure")
{
$('#reg_panel').append('<span id="res_msg">Something Went Wrong try again Latter</span>');
}
});
}
});
Just telling the case
if(res)
{
var email=chkmail(); // for getting the result in var email, ajax will wait until the success
}
if(email) // In your case before completing the ajax request, javascript come to this line and won't return true. So it it always go to else part.
You can do the user creation on success of chkmail success part. It will work fine
Error in your first line of validateregForm() function,
change
if($('#u_name').val=="" || !IsEmail($('#u_email').val())
to
if($('#u_name').val() =="" || !IsEmail($('#u_email').val())
^ `.val()` here.
You need to learn about asynchronously and synchronously concepts. Ajax calls are usually Asynchronously. Simple set the paramter async as false of each ajax request and you will get the result. From documentation
async (default: true)
Type: Boolean
By default, all requests are sent asynchronously (i.e. this is set to true by default).
If you need synchronous requests, set this option to false.
Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation.
Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active.
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().
You need to use a callback to process the result of email validation
function chkmail(email, callback) {
var posting = $.post('http://localhost/tv100.info/index.php/user/chkmail', {
u_email : email
});
posting.done(function(data) {
if (data == 'success') {
callback(true);
} else if (data == 'failure') {
callback(false);
}
});
}
$('#regform').submit(function(event) {
var res = validateregForm()
event.preventDefault();
if (res) {
chkmail($('#u_email').val(), function(valid) {
if (valid) {
$('#email_error').css('display', 'none');
$('#email_msg').css('display', 'block');
$('#loading2').show();
var posting = $.post('http://localhost/tv100.info/index.php/user/create_user', $("#regform").serialize());
posting.done(function(data) {
$('#loading2').hide();
if (data == "success") {
$('#reg_panel').append('<span id="reg_msg">Registration successful Now You are logged IN</span>');
$('#overlay').fadeOut(300);
$('#login').html('Logout');
$('#sign_in').hide();
$('#cmmnt_field').show();
}
if (data == "failure") {
$('#reg_panel').append('<span id="res_msg">Something Went Wrong try again Latter</span>');
}
});
} else {
$('#email_msg').css('display', 'none');
$('#email_error').css('display', 'block');
}
});
}
});
I am trying to check if the user name is available for use using ajax and codeigniter. I have problem to get the response from the codeingniter controller in my js. file but without success.
Here is the controller function, relevant to the question:
if ($username == 0) {
$this->output->set_output(json_encode(array("r" => true)));
} else {
$this->output->set_output(json_encode(array("r" => false, "error" => "Username already exits")));
}
Rest assured that I do get 1 if username already exists in thedatabase and 0 if it does not exist.
I have the following js.file
// list all variables used here...
var
regform = $('#reg-form'),
memberusername = $('#memberusername'),
memberpassword = $('#memberpassword'),
memberemail = $('#memberemail'),
memberconfirmpassword = $('#memberconfirmpassword');
regform.submit(function(e) {
e.preventDefault();
console.log("I am on the beggining here"); // this is displayed in console
var memberusername = $(this).find("#memberusername").val();
var memberemail = $(this).find("#memberemail").val();
var memberpassword = $(this).find("#memberpassword").val();
var url = $(this).attr("action");
$.ajax({
type: "POST",
url: $(this).attr("action"),
dataType: "json",
data: {memberusername: memberusername, memberemail: memberemail, memberpassword: memberpassword},
cache: false,
success: function(output) {
console.log('I am inside...'); // this is never displayed in console...
console.log(r); // is never shonw in console
console.log(output); is also never displayed in console
$.each(output, function(index, value) {
//process your data by index, in example
});
}
});
return false;
})
Can anyone help me to get the username value of r in the ajax, so I can take appropriate action?
Cheers
Basically, you're saying that the success handler is never called - meaning that the request had an error in some way. You should add an error handler and maybe even a complete handler. This will at least show you what's going on with the request. (someone else mentioned about using Chrome Dev Tools -- YES, do that!)
As far as the parse error. Your request is expecting json data, but your data must not be returned as json (it's formatted as json, but without a content type header, the browser just treats it as text). Try changing your php code to this:
if ($username == 0) {
$this->output->set_content_type('application/json')->set_output(json_encode(array("r" => true)));
} else {
$this->output->set_content_type('application/json')->set_output(json_encode(array("r" => false, "error" => "Username already exits")));
}
I have the following node.js server set up listening to port 9001
var https = require('https');
var fs = require('fs');
var qs = require('querystring');
var options = {
key: fs.readFileSync('privatekey.pem'),
cert: fs.readFileSync('certificate.pem')
};
https.createServer(options, function (req, res) {
res.writeHead(200);
console.log('Request Received!');
console.log(req.method);
if (true || req.method == 'POST') {
var body = '';
req.on('data', function (data) {
body += data;
});
req.on('end', function () {
console.log(body);
var POST = qs.parse(body);
console.log(POST);
});
}
res.end("hello, world\n");
}).listen(9001);
and I am trying to get this server to respond to an AJAX call
function form_save()
{
console.log("submitted!");
var data_obj = {
data1: "item1",
data2: "item2"
}
$.ajax({
url: 'https://adam.testserver.com:9001/',
type: "POST",
dataType: "json",
data: data_obj,
success: function() {
console.log("success!");
},
complete: function() {
console.log("complete!");
}
});
}
There are two problems occurring with my arrangement. The first is that if I start the server and then click the button that triggers my form_save() the node server does not respond and I get the following error:
submitted!
OPTIONS https://adam.testserver.com:9001/ Resource failed to load
jQuery.extend.ajaxjquery.js:3633
$.ajaxjquery.validate.js:1087
form_savew_worksheet.php:64
confirm_deletew_worksheet.php:95
jQuery.event.handlejquery.js:2693
jQuery.event.add.handlejquery.js:2468
w_worksheet.php:73
complete!
At this point if I access that url directy (https://adam.testserver.com:9001/) I get the expected "hello, world" output as well as the console message "Request Received!
GET". From this point on if I click the button to trigger my AJAX call I get a new error.
submitted!
XMLHttpRequest cannot load https://adam.testserver.com:9001/. Origin
https://adam.testserver.com is not allowed by Access-Control-Allow-Origin.
w_worksheet.php:73
complete!
I don't understand why I get this message as both my form and node server reside on the same server. Thanks for taking the time to read, I appreciate any help I can get on this. I've been stuck for a while now!
You've run into the Cross-Origin Resource Sharing (CORS) specification.
Note the OPTIONS in your output. The OPTIONS HTTP Verb is used by the browser to query the web server about the URL, not to GET its contents or POST data to it.
Your server doesn't respond with the correct header data on a CORS request, so your browser assumes it has no rights to access the data, and refuses to GET or POST to the URL.
If you truly want to let any website in the world run that AJAX request, you can do something similar to the following:
function handleOptions(request, response) {
response.writeHead(200, {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Method": "POST, GET, OPTIONS",
"Access-Control-Allow-Headers": request.headers["access-control-request-headers"]
});
response.end();
}
function server(request, response) {
if(request.method == "POST") {
handlePost(request, response);
} else if(request.method == "OPTIONS") {
handleOptions(request, response);
} else {
handleOther(response);
}
}
https.createServer(sslObj, server).listen(9001);
You can fill in the details and whether you should handle GET separately, and so on (handleOther should return an appropriate error code for each request method you don't support).
I've got a piece of code that look like this.
app.get('/auth/facebook', function( request, response ) {
if( request.session.user ){
response.render( 'index.jade' );
} else {
request.authenticate(['facebook'], function(error, authenticated) {
if( authenticated ) {
request.session.user = request.getAuthDetails().user;
response.writeHead(303, { 'Location': "/auth/facebook" });
}
});
}
});
If there is a user in session it will render the page, if not it will get a user from Facebook and store that in a session variable and reload the page... and render it. It works perfectly fine. But I want to trigger that piece of code via AJAX and do something like this:
app.get('/auth/facebook', function( request, response ) {
response.contentType('application/json');
if( request.session.user ){
response.send(JSON.stringify({'authenticated':true}));
} else {
request.authenticate(['facebook'], function(error, authenticated) {
if( authenticated ) {
request.session.user = request.getAuthDetails().user;
response.writeHead(303, { 'Location': "/auth/facebook" });
} else {
response.send(JSON.stringify({'authenticated':false}));
}
});
}
});
But that doesn't work. It says "Can't use mutable header APIs after sent" and puts it self in an endless loop saying "Can't render headers after they are sent to the client." over and over again.
Am I going about this the wrong way? I want my server code to connect with Facebook without the need of a page reload.