div only showing up when debugging - javascript

I got a piece of code which drives me insane.
I am loading some Data from the server which takes some time, therefore I would like to display a "loading-icon". But the icon is not showing up, so I debugged the code in Chrome and then it is working.
$(".k-loading-mask").show();
//loading the data from the server
var purchaseInvoiceItems = getOpenPurchaseInvoiceItems(id);
viewmodel.Items = ko.mapping.fromJS(purchaseInvoiceItems, {}, viewmodel.Items);
var prepaymentableOrders = getPrepaymentableOrders(id);
viewmodel.PrepaymentableOrders = ko.mapping.fromJS(prepaymentableOrders, {}, viewmodel.PrepaymentableOrders);
//loading done... hide the loading-icon.
$("div.k-loading-mask").hide();
EDIT:
function getOpenPurchaseInvoiceItems(id) {
var result = jQuery.ajax({
url: '/purchaseinvoices/getopenpurchaseinvoiceitems',
data: JSON.stringify({ supplierId: id }),
async: false,
type: 'POST',
contentType: "application/json"
});
var json = result.responseText;
var purchaseInvoiceItems = eval("(" + json + ")");
return purchaseInvoiceItems;
}
function getPrepaymentableOrders(id) {
var result = jQuery.ajax({
url: '/purchaseinvoices/getprepaymentableorders',
data: JSON.stringify({ supplierId: id }),
async: false,
type: 'POST',
contentType: "application/json"
});
var json = result.responseText;
var purchaseInvoiceItems = eval("(" + json + ")");
return purchaseInvoiceItems;
}
EDIT2
After refactoring the calls to async ajax I ran into the problem, that the done() of getOpenPurchaseInvoiceItems is never called. The done() of getPrepaymentableOrders is called when I call the function directly.
But Chrome Networkanalysis tells me the networktransaction is finished after ~3 seconds.
Maris answer is also not working for me, done() is never called.
function getOpenPurchaseInvoiceItems(id) {
$(".k-loading-mask").show();
jQuery.ajax({
url: '/purchaseinvoices/getopenpurchaseinvoiceitems',
data: JSON.stringify({ supplierId: id }),
type: 'POST',
contentType: "application/json"
}).done(function (data) { //This done is never called.
viewmodel.Items = ko.mapping.fromJS(data, {}, viewmodel.Items);
getPrepaymentableOrders(id);
});
}
//This one works like a charm when called directly
function getPrepaymentableOrders(id) {
jQuery.ajax({
url: '/purchaseinvoices/getprepaymentableorders',
data: JSON.stringify({ supplierId: id }),
type: 'POST',
contentType: "application/json",
}).done(function (data) {
viewmodel.PrepaymentableOrders = ko.mapping.fromJS(data, {}, viewmodel.PrepaymentableOrders);
$("div.k-loading-mask").hide();
});
}
EDIT 3
Added an error-callback, which actually gets fired.
status 200
statusText OK
responseText (The Json of the result-items)
I don't quiet get why the result has an error ...
Fun-Fact:
This works, and it seems that my predecessor had the same problems, because this code is a modified version of my predecessors code.
.error(function (data) {
var json = data.responseText;
var purchaseInvoiceItems = eval("(" + json + ")");
viewmodel.Items = ko.mapping.fromJS(purchaseInvoiceItems, {}, viewmodel.Items);
getPrepaymentableOrders(id);
});
Seems like the result cannot be parsed directly?!
Fiddler Response
HTTP/1.1 200 OK
Server: ASP.NET Development Server/11.0.0.0
Date: Mon, 28 Sep 2015 11:29:15 GMT
X-AspNet-Version: 4.0.30319
X-AspNetMvc-Version: 3.0
Cache-Control: private, s-maxage=0
Content-Type: application/json; charset=utf-8
Content-Length: 126537
Connection: Close
[{"GoodsReceiptItemId":311360,"PurchaseOrderNumber":"BE0010018","SupplierProductNumber":"205.00-122","ProductNumber":"205.00-122","SupplierDeliveryNumber":"5503","GoodsReceiptDate":new Date(1442527200000),"Description":"001-4631-00, \"L-A-EE\"","ShouldBePayed":false,"Amount":500.00000,"Price":2.66000,"PriceUnit":1.00000,"TotalPrice":1330.00000,"PurchaseOrderId":309360,"ProductId":4792,"GoodsReceiptId":299080,"Id":0,"HasBeenSaved":false,"Errors":{"Errors":[],"HasAnyError":false,"HasSumError":false},....]

Since in the javascript there is only one thread and you are running sync calls to the api, UI is getting freezed until the requests is done. That is why you don't see the loading bar at all. So, you have to use async calls and promises to achieve what you want.
The next code should work.
function getOpenPurchaseInvoiceItems(id) {
return $.post('/purchaseinvoices/getopenpurchaseinvoiceitems', { supplierId: id });
}
function getPrepaymentableOrders(id) {
return $.post('/purchaseinvoices/getprepaymentableorders', { supplierId: id });
}
$(".k-loading-mask").show();
//loading the data from the server
var purchaseInvoiceItemsPromise = getOpenPurchaseInvoiceItems(id);
var prepaymentableOrdersPromise = getPrepaymentableOrders(id);
$.when(purchaseInvoiceItemsPromise, prepaymentableOrdersPromise ).done(function(purchaseInvoiceItems, prepaymentableOrders){
viewmodel.Items = ko.mapping.fromJS(purchaseInvoiceItems, {}, viewmodel.Items);
viewmodel.PrepaymentableOrders = ko.mapping.fromJS(prepaymentableOrders, {}, viewmodel.PrepaymentableOrders);
$("div.k-loading-mask").hide();
})
Never use the synchronous ajax calls. If you for some reason want to use synchronous calls then you definitely doing something wrong.

Try using asynchronous calls, like so:
jQuery.ajax({
url: '/purchaseinvoices/getopenpurchaseinvoiceitems',
data: JSON.stringify({ supplierId: id }),
type: 'POST',
contentType: "application/json"
}).done(function(purchaseInvoiceItems){
//.....
})
PS: never use "eval". If you're getting JSON, and the headers say that it's JSON, jquery is smart enough to transform the result to the actual object.
If however you need to convert a JSON string to object, use JSON.parse

Related

jQuery .ajax() - add query parameters to POST request?

To add query parameters to a url using jQuery AJAX, you do this:
$.ajax({
url: 'www.some.url',
method: 'GET',
data: {
param1: 'val1'
}
)}
Which results in a url like www.some.url?param1=val1
How do I do the same when the method is POST? When that is the case, data no longer gets appended as query parameters - it instead makes up the body of the request.
I know that I could manually append the params to the url manually before the ajax request, but I just have this nagging feeling that I'm missing some obvious way to do this that is shorter than the ~5 lines I'll need to execute before the ajax call.
jQuery.param() allows you to serialize the properties of an object as a query string, which you could append to the URL yourself:
$.ajax({
url: 'http://www.example.com?' + $.param({ paramInQuery: 1 }),
method: 'POST',
data: {
paramInBody: 2
}
});
Thank you #Ates Goral for the jQuery.ajaxPrefilter() tip. My problem was I could not change the url because it was bound to kendoGrid and the backend web API didn't support kendoGrid's server paging options (i.e. page, pageSize, skip and take). Furthermore, the backend paging options had to be query parameters of a different name. So had to put a property in data to trigger the prefiltering.
var grid = $('#grid').kendoGrid({
// options here...
dataSource: {
transport: {
read: {
url: url,
contentType: 'application/json',
dataType: 'json',
type: httpRequestType,
beforeSend: authentication.beforeSend,
data: function(data) {
// added preFilterMe property
if (httpRequestType === 'POST') {
return {
preFilterMe: true,
parameters: parameters,
page: data.page,
itemsPerPage: data.pageSize,
};
}
return {
page: data.page,
itemsPerPage: data.pageSize,
};
},
},
},
},
});
As you can see, the transport.read options are the same options for jQuery.ajax(). And in the prefiltering bit:
$.ajaxPrefilter(function(options, originalOptions, xhr) {
// only mess with POST request as GET requests automatically
// put the data as query parameters
if (originalOptions.type === 'POST' && originalOptions.data.preFilterMe) {
options.url = options.url + '?page=' + originalOptions.data.page
+ '&itemsPerPage=' + originalOptions.data.itemsPerPage;
if (originalOptions.data.parameters.length > 0) {
options.data = JSON.stringify(originalOptions.data.parameters);
}
}
});

Getting an AJAX GET request to work with Express.js

I am using node.js and Express.js on the back end, and am trying to make a server call from the client via AJAX.
So I have this POST request that works fine with AJAX:
node.js/Express.js:
app.post('/createNewThing', function(req, res) {
var userInput = req.body.userInput;
if (userInput) {
res.send('It worked!');
}
});
Client Side/AJAX request:
var userInputForm = $('#userInputForm.val()')
$.ajax({
url: "/createNewThing",
type: "POST",
data: "userInput=" + userInputForm,
dataType: "text",
success: function(response, status, http) {
if (response) {
console.log('AJAX worked!);
}
}
});
The userInputForm comes from an HTML form.
This POST request works fine. But I want to change this to a GET request. If I change app.post to app.get, and change type in the AJAX call to GET, I get this 500 error:
GET /createNewThing?userInput= 500
When you make a GET request, the data appears in the query string (of the URL in the request headers). It doesn't appear in the request body. There is no request body.
When you try to read from the request body, you are trying to access a property of an undefined object, which triggers an exception and cause an internal server error.
This answer explains how to read a query string:
var id = req.query.id; // $_GET["id"]
So
var userInput = req.query.userInput;
I think var userInputForm = $('#userInputForm.val()') will get error or get wrong data..This may be the reason for the error. Due to userInputForm may not be a string and concatenate with userInput=
Actually it is bad data.
And for the data in ajax, you should modify data from data: "userInput=" + userInputForm,
to:
data: {
userInput: userInputForm
},
dataType: "json"
And var userInputForm = $('#userInputForm.val()')
to var userInputForm = $('#userInputForm').val();
At last, you could modify as bellow, I believe it works:
var userInputForm = $('#userInputForm').val();
$.ajax({
url: "/createNewThing?userInput=" + userInputForm,
type: "GET",
success: function(response, status, http) {
if (response) {
console.log('AJAX worked!);
}
}
});

Pass object from javascript to Perl dancer framework

I have following ajax code to pass values to dancer framework.
BookSave: function(data) {
### data is an object that contain more than one key value pair
var book = Book.code;
$.ajax ({
type: "GET",
url : 'textbook/save/' + book + '/' + data,
success: function(data) {
if(data.status == 1) {
alert("success");
} else {
alert("fail");
}
},
});
},
In dancer:
any [ 'ajax', 'get' ] => '/save/:book/:data' => sub {
set serializer => 'JSON';
my $book = params->{book};
my $data = params->{data}; ## This I am getting as object object instead of hash
};
Is there any way to pass object from js and getting as hash in dancer?
First and foremost, consider using the http PUT or POST verbs, and not GET. Not only is doing so more semantically correct, it allows you to include more complex objects in the http body, such as your 'data' hash (serialized, per my comments below).
I've had limited success with Dancer's native AJAXy methods, plus there is a bug that causes problems in some versions of Firefox. So instead, I serialize and then deserialize the JSON object.
Suggested changes (note I suggested changes to your routes as well):
$.ajax ({
type: "PUT",
url : '/textbook/' + book,
data: {
myhash : JSON.stringify(data)
},
dataType: 'json',
contentType: 'application/json',
success: function (response) {
if (response.status == 1) {
alert("success")
} else {
alert("fail")
}
}
})
and your Perl Dancer code changes as follows:
any [ 'ajax', 'put' ] => '/textbook/:book' => sub {
set serializer => 'JSON';
my $book = param('book');
my $data = from_json(param('myhash'));
};
I did not go as far as testing this code, but it should at least give you a good starting point to finish solving this problem.
Good luck with your project!

Why two ajax request is called with following JS code?

I have following code to pull data from server. I want to call it on document.ready(). And I expect first request is made to server, get response and second request is made and so on.
But I see in Firebug, there are two request to server is being made at initial page load. I am not sure why two request.
Here is my code.
;var EVENTS = {};
;(function($) {
EVENTS.Collector = {
events: [],
getEventsData: function() {
var postData = {
'jsonrpc': '2.0',
'id': RPC.callid(),
'method': "events.getNewOrUpdated",
'params': {},
'auth': RPC.auth()
};
var events_request = $.ajax({
url: RPC.rpcurl(),
contentType: 'application/json-rpc',
type: "POST",
data: JSON.stringify(postData),
timeout: 30000
});
events_request.done(function(results) {
//console.log("Info " + results);
if (results.result.result !== null) {
if (EVENTS.Collector.events.length !== 0) {
alert(EVENTS.Collector.events.length);
} else {
alert(EVENTS.Collector.events.length);
}
}
});
events_request.fail(function(results) {
//console.error("Error " + results);
$("Error Message").insertAfter('.error');
});
events_request.always($.proxy(this.getEventsData, this));
}
};
})(jQuery);
EVENTS.Collector.getEventsData(); //function call
Thanks in advance
If you remove the code below does it call at all?
EVENTS.Collector.getEventsData(); //function call
By default ajax request are asynchronous. If you want each request to be kind of "blocking" until done, then proceed to next, you can send sync request just by adding async: false to ajax call parameters.
Give a try to the following snippet, if it's what you meant to do..??.
var events_request = $.ajax({
url: RPC.rpcurl(),
contentType: 'application/json-rpc',
type: "POST",
async: false,
data: JSON.stringify(postData),
timeout: 30000
});
Consider that sync requests causes the interpreter function pointer to wait till any result come back from the call, or till request timeout.

cakephp 2.2 retrieve json data in controller

I'm trying to send JSON data from a web page using JQuery, like this:
$.ajax({
type: "post", // Request method: post, get
url: "http://localhost/ajax/login",
data: '{username: "wiiNinja", password: "isAnub"}',
dataType: "json", // Expected response type
contentType: "application/json",
cache: false,
success: function(response, status) {
alert ("Success");
},
error: function(response, status) {
alert('Error! response=' + response + " status=" + status);
}
});
In cake2.2, I have a controller named Ajax that has a method named "login", like this:
public function login($id = null)
{
if ($this->RequestHandler->isAjax())
{
$this->layout = 'ajax'; // Or $this->RequestHandler->ajaxLayout, Only use for HTML
$this->autoLayout = false;
$this->autoRender = false;
$response = array('success' => false);
$data = $this->request->input(); // MY QUESTION IS WITH THIS LINE
debug($data, $showHTML = false, $showFrom = true);
}
return;
}
I just want to see if I'm passing in the correct data to the controller. If I use this line:
$data = $this->request->input();
I can see the debug printout:
{username: "wiiNinja", password: "isCool"}
I read in the CakePHP manual 2.x, under "Accessing XML or JSON data", it suggests this call to decode the data:
$data = $this->request->input('json_decode');
When I debug print $data, I get "null". What am I doing wrong? Is my data passed in from the Javascript incorrect? Or am I not calling the decode correctly?
Thanks for any suggestion.
============= My own Edit ========
Found my own mistake through experiments:
When posting through Javascript, instead of this line:
data: '{username: "wiiNinja", password: "isAnub"}',
Change it to:
data: '{"username": "wiiNinja", "password": "isAnub"}',
AND
In the controller code, change this line:
$data = $this->request->input('json_decode');
To:
$data = $this->request->input('json_decode', 'true');
It works.
Dunhamzzz,
When I followed your suggestions, and examine the "$this->request->params" array in my controller code, it contains the following:
array(
'plugin' => null,
'controller' => 'ajax',
'action' => 'login',
'named' => array(),
'pass' => array(),
'isAjax' => true
)
As you can see, the data that I'm looking for is not there. I've already got the the proper routes code. This is consistent with what the documentation for 2.x says here:
http://book.cakephp.org/2.0/en/controllers/request-response.html
So far, the only way that I found to make it work, is as stated above in "My own Edit". But if sending a JSon string to the server is not the right thing to do, I would like to fix this, because eventually, I will have to handle third party code that will send JSon objects.
The reason you are struggling wit the data is because you are sending a string with jQuery, not a proper javascript object (JSON).
$.ajax({
type: "post", // Request method: post, get
url: "http://localhost/ajax/login",
data: {username: "wiiNinja", password: "isAnub"}, // outer quotes removed
dataType: "json", // Expected response type
contentType: "application/json",
cache: false,
success: function(response, status) {
alert ("Success");
},
error: function(response, status) {
alert('Error! response=' + response + " status=" + status);
}
});
Now the data will be available as a PHP array in $this->request->params.
Also for sending a JSON response, please see this manual page. Most of your code there can be reduced to just 2 lines...
//routes.php
Router::parseExtensions('json');
//Controller that sends JSON
$this->set('_serialize', array('data'));

Categories

Resources