Kendo get data from remote service, do paging locally - kendo-ui

Code:
var url = base_url + "/api/v1/users/getUsers";
var dataSource = new kendo.data.DataSource({
transport: {
read: function (options) {
$.ajax({
type: 'GET',
url:url,
dataType: 'json',
data: { searchTerm: $("#searchTerm").val().trim() },
success: function (result) {
options.success(result);
},
error: function (result) {
options.error(result);
}
});
}
},
schema: {
data: function (result) {
return result.model;
},
total: function (result) {
return result.model.length;
},
},
pageSize: 5
});
$("#matches").kendoListView({
dataSource: dataSource,
autoBind: false, // if set to false the widget will not bind to the data source during initialization.
template: kendo.template($("#matchesListViewTemplate").html())
});
$("#pager").kendoPager({
dataSource: dataSource,
autoBind: false
});
$(document).keypress(function (e) {
if (e.which == 13) {
e.preventDefault();
var searchTerm = $("#searchTerm").val().trim();
if (searchTerm.length < 1)
return;
dataSource.read();
dataSource.page(1); // makes another call to the remote service
}
});
Because data source is remote, when we call dataSource.page(1), kendo issues another call to the remote service. This behaviour is described in this so post:
If you are doing server side paging it should be enough doing grid.dataSource.page(1) since this will invoke the read exactly as you already realized.
What must I change so that after I search with new searchTerm, API call would be done only once and pager would go to page 1 without making another call?
I tried with dataSource.query() but still no luck? I hope I demonstrated enough.

Solution is to call dataSource.page(1) when dataSource.read() gets data / is done.
$(document).keypress(function (e) {
if (e.which == 13) {
e.preventDefault();
var searchTerm = $("#searchTerm").val().trim();
if (searchTerm.length < 1)
return;
dataSource.read().done(function() {
// in case remote service returns empty result set (but still http 200 code)
// page() makes another request (if data() is empty it makes another request)
// therefore we must check data length/total
if( dataSource.total() > 0)
dataSource.page(1);
}
});
If the read request's response have not arrived yet or if an error occurs, another read request is allowed (in order to fetch data). DataSource.read() makes asynchronously request and then dataSource.page(1) starts to execute. DataSource.page(1) function checks if there is any data read, if it's not it executes again read method - therefore we got 2 calls as you mentioned it. Because of asynchronously call this scenario may happen.

Related

Ajax Call to mvc controller action is very slow when SignalR is fetching data

My App Flow
In my App - Dashboard,
I have the SignalR scripts included which fetches new data as and when new data arrives from the device
It also has ajax script that hits on the Controller to fetch data from the back end - when a Get button is clicked.
Ajax Call mentioned in #2 above takes more than 2 minutes if new data keeps getting in (i.e when SignalR is continuously fetching data and publishing to all connected clients).
Else
the Ajax Call Point#2 above takes very less time to get the data.
Any ideas, better way, ... on how I can avoid the slowness in the ajax call #2 even if SignalR continuously fetches data.
This is my #2 Ajax Call ==> Call to the Home Controller Action Method SignalList
$('#DeviceID').on('change', function () {
$('#DeviceName').text("Device : " + $('#DeviceID option:selected').text());
$.ajax({
url: "/Home/SignalList",
type: "POST",
data: { deviceID: $('#DeviceID').val() },
//contentType: "application/json; charset=utf-8",
dataType: "html",
//cache: false,
//async: true,
success: function (result) {
//alert("AAA");
$('#signalCheckListBox').html(result);
},
failure: function (response) {
alert(response.responseText);
},
error: function (response) {
alert(response.responseText);
}
});
This is SignalR script
(function () {
// Defining a connection to the server hub.
var signalHub = $.connection.signalHub; //alert("ACCC");
// Setting logging to true so that we can see whats happening in the browser console log. [OPTIONAL]
$.connection.hub.logging = true;
// Start the hub
$.connection.hub.start();
// This is the client method which is being called inside the SignalHub constructor method every 3 seconds
signalHub.client.SendSignalData = function (signalData) {
dModel = signalData;
updateSignalData(signalData);//<============ # Statekemnt A
};
$.connection.hub.disconnected(function () {
setTimeout(function () {
$.connection.hub.start();
}, 5000); // Restart connection after 5 seconds.
}); }());
The statement A marked above is a method which (1)updates different html elements in the UI and also (2)sends an email on a condition.
For sending the email too it hits the same controller Home (??? Would that be the problem???)
The email ajax call is below ==> Its a call to Home Controller Action Method Communicate
function email(alarmSignalInfo) {
$.ajax({
url: "/Home/Communicate",
type: "POST",
dataType: "json",
//data: { alarmSignalInfo: JSON.stringify(alarmSignalInfo) },
data: { alarmSignalInfo: alarmSignalInfo },
//cache: false,
//async: true,
success: function (result) { onSuccess(result); }
}); }

Ajax wait on success before next iteration in .each loop

I have an ajax call inside a .each loop wrapped in a setInterval function.
This handles updating of many divs on a dashboard with just a few lines of code on the html page.
I am worried about server lag vs client side speed. What will happen if the server has not responded with the data before the loop moves on to the next iteration?
So, my question is, can the loop be paused until the success is executed?
Ajax call:
setInterval(function() {
$(".ajax_update").each(function(){
$.ajax({
type: "POST",
dataType: "json",
url: "ajax/automated_update/confirmed_appointments.php",
data: "clinic_id=<? echo $clinic_id ?>&tomorrow=<? echo $tomorrow ?>&"+$(this).data('stored'), // serializes the form's elements.
success: function(data)
{
$(data[0]).html(data[1]);
}
});
});
}, 5000); //5 seconds*
</script>
I have looked into .ajaxComplete() but I dont see how to apply this as a solution.
I have also looked at turning the loop into something that calls itself like:
function doLoop() {
if (i >= options.length) {
return;
}
$.ajax({
success: function(data) {
i++;
doLoop();
}
});
}
But would that not interfere with .each? I dont understand how that would play nice with .each and looping based on my div class.
I just cant figure it out! Any help would be appreciated.
I was able to get .when working with the ajax call, but I dont understand how to make .when do what I need (stop the loop until the ajax call is done).
$(".ajax_update").each(function(){
$.ajax({
type: "POST",
dataType: "json",
url: "ajax/automated_update/confirmed_appointments.php",
data: "clinic_id=<? echo $clinic_id ?>&tomorrow=<? echo $tomorrow ?>&"+$(this).data('stored'), // serializes the form's elements.
success: function(data)
{
$(data[0]).html(data[1]);
}
});
$.when( $.ajax() ).done(function() {
alert("Finished it");
});
});
After thinking about your question a bit, perhaps a good solution would be to put an event in place that would trigger a new set of updates with a minimum time between your dashboard updates. This would ensure that all your updates process, that we do wait a minimum time between updates and then trigger the update cycle once again. Thus if you DO encounter any delayed ajax responses you do not try another until the previous one has all completed.
I have not fully tested this code but is should do what I describe:
//create a dashboard object to handle the update deferred
var dashboard = {
update: function (myquery) {
var dfr = $.Deferred();
$.ajax({
type: "POST",
dataType: "json",
url: "ajax/automated_update/confirmed_appointments.php",
data: "clinic_id=<? echo $clinic_id ?>&tomorrow=<? echo $tomorrow ?>&" + myquery,
success: dfr.resolve
});
return dfr.promise();
}
};
//create a simple deferred wait timer
$.wait = function (time) {
return $.Deferred(function (dfd) {
setTimeout(dfd.resolve, time);
});
};
// use map instead of your .each to better manage the deferreds
var mydeferred = $(".ajax_update").map(function (i, elem) {
return dashboard.update($(this).data('stored')).then(function (data, textStatus, jqXHR) {
$(data[0]).html(data[1]);
});
});
//where I hang my dashboardupdate event on and then trigger it
var mydiv = $('#mydiv');
var minimumDashboardUpdate = 5000;
$('#mydiv').on('dashboardupdate', function () {
$.when.apply($, mydeferred.get())
.then(function () {
$.when($.wait(minimumDashboardUpdate)).then(function () {
mydiv.trigger('dashboardupdate');
});
});
});
mydiv.trigger('dashboardupdate');

Kendo UI - DataSource works when using fetch(), but not read()

I have a Kendo UI DataSource that works when I use fetch(), but when I use the exact same configurtation with read() it fails. This is a problem as I need to retrieve data more than once and I can't do that with fetch().
Here is the DataSource code -
var FieldsDataSource = new kendo.data.DataSource({
transport: {
read: {
url: "../WebServiceAddress",
dataType: "json",
type: "POST",
contentType: 'application/json; charset=utf-8',
cache: false
},
parameterMap: function() {
return "{some mapping that has been confirmed to work}";
},
schema: {
data: function (data) {
if (data && data.d) {
//execution gets to here and stops
return data.d;
}
else {
return [];
}
},
}
});
Here is the code that calls the DataSource.read() function -
function loadFields() {
FieldsDataSource.read(function() {
var data = this.data();
if (data.length > 0) {
for (var i = 0; i < data.length; i++) {
var dataitem = data[i].Key;
$("#" + dataitem + "_field").prop("checked", data[i].Value);
}
}
});
}
If I change FieldsDataSource.read(function() to FieldsDataSource.fetch(function() everything works, but that doesn't make sense as I was under the improession that read and fetch do the same thing the difference being fetch only gets data once.
What I do know is that the data is being returned from the server, I can see it in fiddler - but the execution stops in the schema section where I flagged it in my code sample.
Apologies if I am asking a really obvious question, but I'm very new to Kendo.
have a look at the kendo demo site, this post explains how to read remote data quite nicely. I beleive the schema.data requires only string value. Configure your model and parse and then just call read(), your datasource.data collection will get populated and then you can play with it.
Also note that datasource.read() is async, thefore you populatefields method should be called from complete event of the datasource, not other way around. eg you might have no data in when populating.
transport: {
read: {
url: "../WebServiceAddress",
dataType: "json",
type: "POST",
contentType: 'application/json; charset=utf-8',
cache: false,
complete : function () { }
},

Kendo Datasource Transport custom function not getting called

Im experiencing a rather annoying bug (?) in Kendo UI Datasource.
My Update method on my transport is not getting called when I pass a custom function, but it does work if I just give it the URL.
This works:
...
transport: {
update: { url: "/My/Action" }
}
...
This does not
...
transport: {
update: function(options) {
var params = JSON.stringify({
pageId: pageId,
pageItem: options.data
});
alert("Update");
$.ajax({
url: "/My/Action",
data:params,
success:function(result) {
options.success($.isArray(result) ? result : [result]);
}
});
}
}
...
The function is not getting invoked, but an ajax request is made to the current page URL, and the model data is being posted, which is rather odd. Sounds like a bug to me.
The only reason I have a need for this, is because Kendo can't figure out that my update action returns only a single element, and not an array - so, since I dont want to bend my API just to satisfy Kendo, I though I'd do it the other way around.
Have anyone experienced this, and can point me in the right direction?
I also tried using the schema.parse, but that didn't get invoked when the Update method was being called.
I use myDs.sync() to sync my datasource.
Works as expected with the demo from the documentation:
var dataSource = new kendo.data.DataSource({
transport: {
read: function(options) {
$.ajax( {
url: "http://demos.kendoui.com/service/products",
dataType: "jsonp",
success: function(result) {
options.success(result);
}
});
},
update: function(options) {
alert(1);
// make JSONP request to http://demos.kendoui.com/service/products/update
$.ajax( {
url: "http://demos.kendoui.com/service/products/update",
dataType: "jsonp", // "jsonp" is required for cross-domain requests; use "json" for same-domain requests
// send the updated data items as the "models" service parameter encoded in JSON
data: {
models: kendo.stringify(options.data.models)
},
success: function(result) {
// notify the data source that the request succeeded
options.success(result);
},
error: function(result) {
// notify the data source that the request failed
options.error(result);
}
});
}
},
batch: true,
schema: {
model: { id: "ProductID" }
}
});
dataSource.fetch(function() {
var product = dataSource.at(0);
product.set("UnitPrice", product.UnitPrice + 1);
dataSource.sync();
});
Here is a live demo: http://jsbin.com/omomes/1/edit

synchronize two ajax jquery function

I have two function of jQuery. Both the functions are calling jQuery ajax.
both have property async: false.
In both the function I am redirecting on basis of some ajax response condition.
In the success of first function I am calling the another function and then redirecting to another page. But my first function is not redirecting because my second function is not waiting of the response of the first function.
Hope problem is clear from my question.
my first function is as below
function fnGetCustomer() {
function a(a) {
$("#loading").hide();
//on some condition
//other wise no redirection
self.location = a;
}
var b = $("input#ucLeftPanel_txtMobile").val();
"" != b && ($("#loading").show(), $.ajax({
type: "POST",
url: "Services/GetCustomer.ashx",
data: { "CustMobile": b },
success: a,
async: false,
error: function () {
$("#loading").hide();
}
}));
}
and my second function I am calling the first function
function fnSecond() {
$.ajax({
type: "POST",
url: "some url",
async: false,
data: { "CustMobile": b },
success: function(){
fnGetCustomer();
//if it has all ready redirected then do not redirect
// or redirect to some other place
},
error: function () {
$("#loading").hide();
}
}));
}
I am using my first function all ready. So I don't want to change my first function.
A set up like this should work;
$.ajax({
data: foo,
url: bar
}).done(function(response) {
if (response == "redirect") {
// redirect to some page
} else {
$.ajax({
data: foo,
url: bar
}).done(function(response2) {
if (response2 == "redirect") {
// redirect to some other page
} else {
// do something else
}
});
}
});​
I've not tested doing something like this, but that's roughly how I'd start off
If you don't need the result of the first AJAX call to be able to send the second you could add a counter to keep track of the calls. Since you can send both calls at the same time it'll be a lot more responsive.
var requestsLeft = 2;
$.ajax({
url: "Firsturl.ashx",
success: successFunction
});
$.ajax({
url: "Secondurl.ashx",
success: successFunction
});
function successFunction()
{
requestsLeft--;
if (requestsLeft == 0)
doRedirectOrWhatever();
}
If you absolutely need to do them in order you could do something like this. My example expects a json response but that's no requirement for this approach to work.
var ajaxurls = ["Firsturl.ashx", "Secondurl.ashx"]
function doAjax()
{
$.ajax({
url: ajaxurls.shift(), // Get next url
dataType: 'json',
success: function(result)
{
if (result.redirectUrl) // or whatever requirement you set
/* redirect code goes here */
else if (ajaxurls.length>0) // If there are urls left, run next request
doAjax();
}
});
}
doAjax();

Resources