paging not moving to new data in kendogrid - javascript

Please note that at this time I am new to ASP.NET MVC, JavaScript and Kendo. The Kendo grid paging works for the first 500 records returned, but won't allow paging to download more data from the server past 500. Here is my controller:
public ActionResult ExecuteTestRule(string ruleId, string ruleSql, string uwi, List<PdsMatchRuleParam> parameters = null)
{
if (Request.Url != null)
{
var query = PaginationQuery.Parse(Request.QueryString);
var upperLimit = query.FromUpper;
var lowerLimit = query.FromLower;
var dataSource = new MatchDataSource();
List<DataAccess.DbParameter> dbParameters = null;
var generatedSql = dataSource.GenerateQuerySql(ruleId, ruleSql, uwi, parameters, out dbParameters);
var results = dataSource.ExecuteTestRule(ruleId, generatedSql, dbParameters, upperLimit, lowerLimit).Select(u => new { UWI = u });
var response = new Dictionary<string, object>();
response["result"] = results;
response["rowCount"] = MatchDataSource.GetRowCount(generatedSql, dbParameters);
return Json(response, JsonRequestBehavior.AllowGet);
}
return null;
}
Here are the total number of rows available "rowCount" in the controller:
MatchDataSource.GetRowCount(generatedSql, dbParameters)
91637
Here is the Request.QueryString in the controller:
Request.QueryString
{}
[System.Web.HttpValueCollection]: {}
base {System.Collections.Specialized.NameObjectCollectionBase}: {}
AllKeys: {string[0]}
Pressing this button has no effect:
Here is my JavaScript code:
function bindTestRuleResults() {
PageState.Selected.Old.TestRuleResult = PageState.Selected.TestRuleResult;
var dataSource = new kendo.data.DataSource({
pageSize: 500,
data: PageState.Selected.TestRuleResult,
serverPaging: true
});
Grids.TestRuleResultsGrid.setDataSource(dataSource);
PageState.Selected.TestRuleResult = null;
}
function initTestRuleResultsGrid() {
$(IDS.testRuleResultsGrid).kendoGrid({
autoBind: true,
filterable: false,
navigatable: true,
pageable: {
refresh: true,
pageSizes: [10, 50, 100, 500],
buttonCount: 5
},
scrollable: true,
selectable: true,
serverFiltering: false,
serverPaging: true,
serverSorting: true,
sortable: false,
columns: [
{ field: "UWI", title: "UWI", width: "100%", attributes: { tabindex: "1" } }
],
change: function() {
var selectedDataItem = this.dataItem(this.select());
if (PageState.Selected.TestRuleResult !== selectedDataItem.TestRuleResult) {
PageState.Selected.TestRuleResult = selectedDataItem.TestRuleResult;
testRuleResultsSelectionChanged();
}
},
editable: false
});
// Add vertical scroll bars
$(IDS.testRuleResultsGrid + " .k-grid-content").css({
"overflow-y": "scroll"
});
Grids.TestRuleResultsGrid = $(IDS.testRuleResultsGrid).data('kendoGrid');
}
function execTestRule(uwi) {
$.ajax({
type: 'POST',
url: "ExecuteTestRule",
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({
ruleId: PageState.Selected.RuleId,
ruleSql: PageState.SqlEditor.RuleSql.getValue(),
uwi: "'" + uwi + "'",
parameters: PageState.RuleParameters
}),
schema: {
errors: function(response) {
return response.error;
},
data: function(response) {
return response.result;
},
total: function(response) {
return response.rowCount;
}
},
success: function(matchedUwiList) {
PageState.TestRuleResult = matchedUwiList.result;
var dataSource = new kendo.data.DataSource({
pageSize: 500,
data: matchedUwiList.result,
serverPaging: true
});
Grids.TestRuleResultsGrid.setDataSource(dataSource);
PageState.Selected.ChildUwi = null;
updateButtonStates();
},
error: function(e) {
var errorObject = JSON.parse(e.xhr.responseText);
var errorMessage = errorObject.Message;
//clear old error message
Grids.TestRuleResultsGrid.clearErrorMessage("error-message");
// add new error message
Grids.TestRuleResultsGrid.addErrorMessage("error-message", errorMessage);
}
});
}
It clearly has serverPaging = true in the data source. What am I missing? Do I need to somehow make pageSize dynamic in my JavaScript code? TIA.
UPDATE:
Thank you for the feedback, #Brett. This is how I've simplified the code as you suggested. How do I remove the success: function outside of the ajax part?
function execTestRule(uwi) {
$.ajax({
type: 'POST',
url: "ExecuteTestRule",
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({
ruleId: PageState.Selected.RuleId,
ruleSql: PageState.SqlEditor.RuleSql.getValue(),
uwi: "'" + uwi + "'",
parameters: PageState.RuleParameters
}),
success: function(matchedUwiList) {
PageState.TestRuleResult = matchedUwiList.result;
var dataSource = new kendo.data.DataSource({
schema: {
data: 'results',
total: 'rowCount'
},
pageSize: 500,
serverPaging: true
});
Grids.TestRuleResultsGrid.setDataSource(dataSource);
PageState.Selected.ChildUwi = null;
updateButtonStates();
}
});
}
When the execTestRule function is run, this is the error I'm getting:

You code is confusing to me, but I do see one particular problem. You are not telling the Kendo UI DataSource where your data and row count properties are in the returned object from your controller.
In your controller, you specify that the data is located in the response["results"] property, while the row count is in the response["rowCount"] property. Therefore, your returned object looks like this:
{
results: [...],
rowCount: 91637
}
The Kendo UI DataSource object's schema, by default, expects data to be located in a "data" property and the row count (a.k.a. number of items in data) to be located in the "total" property. Since your object does not conform to convention, you need to tell the data source that your properties are named differently.
var dataSource = new kendo.data.DataSource({
schema: {
data: 'results',
total: 'rowCount'
},
pageSize: 500,
serverPaging: true
});
So, you might say you are doing that already, but look where you defined it. You defined it on the $.ajax() call. That is not correct. The $.ajax() function does not care about schema. The Kendo UI DataSource does.
Kendo UI DataSource API reference
jQuery $.ajax API reference

As #Brett explained, resolved the problem by taking the schema out of the $.ajax() call. Also, started using a transport in the dataSource:
$.widget("myViewGrid", {
// ...
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: "{0}/ViewDataById".format(options.controllerUri),
type: "get",
dataType: "json",
data: {
viewId: view.viewId,
Id: options.Id
}
}
},
schema: {
data: "mydata",
total: "total",
model:dataSourceModel
},
pageSize: view.pageSize,
serverPaging: true,
serverSorting: true,
serverFiltering: true
});
// ...
});

Related

Why Kendo datasource functions is not called?

I am trying to bind returned data from datasource to grid but the problem is that non of my data source functions is called...
transactionHistoryGridDS: new kendo.data.DataSource({
error: function () {
alert("erroe")
},
complete: function () {
alert("completed")
},
success: function () {
alert("success");
},
transport: {
read: {
dataType: "json",
type: 'POST',
url: args.TransactionHistoryUrl,
data: {
id: function () {return vm.transactionHistoryParams.id },
originBranch: function () {return vm.transactionHistoryParams.originBranch },
take: function () {return vm.transactionHistoryParams.take },
skip: function () {return vm.transactionHistoryParams.skip }
}
},
schema: {
parse: function (data) {
alert("hey...")
return data;
},
data: "data",
total: "total",
},
pageSize: 20,
serverPaging: false
}
}),
When i call read datasource through below code
vm.transactionHistoryGridDS.read();
Ajax request is called and data successfully returned from the server,but non of the functions including success and error and complete and parse is called
and consequently, data is not bind to the grid.
I can see some bugs that need to be fixed before your grid will work.
First of all, schema, pageSize, serverPaging is on wrong indent level, it should be on same level as transport not inside it.
transport: {...},
schema: {...},
serverPaging: ...,
pageSize: ...
Every grid should have dataSource property, read will be called automatically and data will be populated, you dont need to set data to grid or call read() function:
$('#grid').kendoGrid({
dataSource: {
transport: {
read: {...}
}
}
});
In your case I assume vm is a grid so you need to set dataSource:transactionHistoryGridDS, check example links below
If you need to send data with request use parameterMap:
$('#grid').kendoGrid({
resizable: true,
filterable: true,
sortable: true,
pageable: {
pageSize: 10,
refresh: true,
pageSizes: [5, 10, 20, 100, 500, 1000]
},
dataSource: {
pageSize: 10,
serverPaging: true,
serverFiltering: true,
transport: {
read: {
url: 'url',
type: 'POST',
dataType: 'JSON',
contentType: 'application/json'
},
update: {...},
destroy: {...},
parameterMap(data, type) {
switch (type) {
case 'read':
let request = {};
request.page = data.page - 1;
request.page_size = data.pageSize;
request.sort = data.sort;
request.filter = data.filter;
return JSON.stringify(request);
case 'destroy':
return kendo.stringify(data);
default:
break;
}
}
}
}
});
There is two way of geting data from kendo dataSource request, first one it with complete function that is called when request and response is finished. The second is promise on every dataSource request.
First example: complete call
Second example: promise call

How to properly code Javascript / Ajax for use with Chart.js

I have a controller action in my MVC project that creates a json record with the components needed. This is working. The issue I am having is bringing it into a chart.js canvas. This will be a pie chart that shows all the related countries with a count of each. Json has this info. Originally this was setup to use google visualization but I want to use chart.js. I just started using it. Creating charts with static data is no issue but I am pulling the info from a SQL table and creating a json to read from.
I have tried using the same structure and calling the data: data[] but it doesn't work I have also tried data: getData, which is a var for the ajax function. I am getting the data per the council on refresh.
Here is my controller Action
public ActionResult CustomersByCountry()
{
CustomerEntities _context = new CustomerEntities();
var customerByCountry = (from c in _context.Addresses
group c by c.Country into g
orderby g.Count() descending
select new
{
Country = g.Key,
CountCustomer = g.Count()
}).ToList();
return Json(new { result = customerByCountry }, JsonRequestBehavior.AllowGet);
}
And here is the JavaScript/ajax - which is nested in a document.ready function with the rest of the charts.
EDIT - changed Ajax - Still not working
OrdersByCountry()
function OrdersByCountry() {
$.ajax({
url: '/admin/CustomersByCountry',
method: "GET",
dataType: "json",
error: function (_, err) {
console.log(_, err)
},
success: function (data) {
console.log (data);
var customer = $("#customerByCountryPieChart").get(0).getContext("2d");
console.log(customer)
var cpieChart = new Chart(customer, {
type: 'pie',
data: data,
options: {
responsive: true,
title: {
display: true,
text: "Customers By Country",
}
}
});
}
});
};
Edit - The now working code is below.
I changed it to get states instead of country, just to clear up possible confusion. It made more sense to me to get States rather than Country at this point. This is working - meaning displaying the graph, I still need to work on the labels etc.
OrdersByStates()
function OrdersByStates() {
$.ajax({
url: '#Url.Action("CustomersByStates", "Admin")',
data: JSON,
contentType: "application/json; charset=utf-8",
method: "get",
dataType: "json",
error: function (_, err) {
console.log(_, err)
},
success: function (response) {
console.log(response);
var jsonresult = response
var labels = jsonresult.result.map(function (e) {
return e.State;
});
var data = jsonresult.result.map(function (e) {
return e.CountCustomer;
});;
var ctx = document.getElementById("CustomerByStatePieChart").getContext("2d");
var cpieChart = new Chart(ctx, {
type: 'pie',
data:
{
datasets: [
{
backgroundColor: ["#46BFBD", "#F7464A"],
hoverBackgroundColor: ["#5AD3D1", "#FF5A5E"],
label: "Orders",
data: data,
}]
},
options: {
responsive: true,
title: {
display: true,
text: "Customers By Country",
}
}
});
}
});
};
});
try:
var cpieChart = new Chart(customer, {
type: 'pie',
data: data.result,
options: {
responsive: true,
title: {
display: true,
text: "Customers By Country",
}
}
});
the response from the server "data" var on your request is {result: LIST}

Bootstrap-table : multiple tables , one function

I am on an custom ajax implementation for bootstrap-table (the documentation : http://bootstrap-table.wenzhixin.net.cn/documentation/) :
For some reason, I would like to have multiple bootstrap Tables (let's call them searchTable1 , searchTable2,etc). Each of these table will be set on a custom date range (30 last days, 60 last days,etc).
I would like to pass a parameter (like the table Jquery selector or any data-myCustomDataAttribute parameter) . How can I do that ? (I tried using call but bootstrap already call it on the ajaxCallback function so It seems I cannot use it here).
It will look like stupid to make x functions that are exactly the same except for two fields depending on the table. Does someone has an idea to do that ?
Here is my code :
$('#searchTable').bootstrapTable({
columns: [{
field: 'product',
title: 'Produit'
} , {
field: 'language',
title: 'Langue'
}, {
field: 'comment',
title: 'Commentaire'
}],
showRefresh: true,
ajax: provideFeedbacksList,
cache: false,
dataField: 'feedbacks',
totalField: 'total_size',
search: false,
sidePagination: 'server',
pagination: true
});
The ajax provider :
// I only used this example : http://issues.wenzhixin.net.cn/bootstrap-table/index.html#options/custom-ajax.html
function provideFeedbacksList(params) {
let tableData = params.data;
let serverCall = {};
// add limits and offset provided by bootstrap table
serverCall["page_offset"] = tableData.offset;
serverCall["page_size"] = tableData.limit;
// retrieve the date range for this table :
// will be easy If something like this was possible : params.jquerySelector.attr("date-range-start")
// will be easy If something like this was possible : params.jquerySelector.attr("date-range-end")
let json = JSON.stringify(serverCall);
$.ajax({
url: baseUri + "/feedbacks",
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: json,
success: function (reponse) {
params.success(reponse);
},
error: function (er) {
params.error(er);
}
});
}
Bonus, the call stack :
Finally found my answer , I have to wrapper it as a function to enable bootstrap table to pass also its data:
Self solved my issue :
js:
function callbacker(test){
console.log(test);
return function (params) {
console.log(params);
console.log(test);
let tableData = params.data;
let serverCall = {};
// add limits and offset provided by bootstrap table
serverCall["page_offset"] = tableData.offset;
serverCall["page_size"] = tableData.limit;
let json = JSON.stringify(serverCall);
$.ajax({
url: baseUri + "/feedbacks",
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: json,
success: function (reponse) {
params.success(reponse);
},
error: function (er) {
params.error(er);
}
});
}
}
html:
$('#searchTable').bootstrapTable({
columns: [{
field: 'product',
title: 'Produit'
} , {
field: 'language',
title: 'Langue'
}, {
field: 'comment',
title: 'Commentaire'
}],
showRefresh: true,
ajax: callbacker("whatEverValueYouWant"),
cache: false,
dataField: 'feedbacks',
totalField: 'total_size',
search: false,
sidePagination: 'server',
pagination: true
});

Loop displaying undefined and I can't see where I've set it wrong

I'm looping through data from a .net web service through jsonp. Similar code works elsewhere but I can't see where i've gone wrong here.
The data is retreived through:
if (pageId === 'alerts') {
var Username = localStorage.getItem("Username");
var SessionKey = localStorage.getItem("SessionID");
console.log(Username);
console.log(SessionKey);
$.mobile.loading( 'show', { theme: "b", text: "Loading", textonly: false});
$.ajax({
crossDomain: true,
contentType: "application/json; charset=utf-8",
url: "http://redacted/GetData.asmx/GetLostAnimals",
data: {Username: Username, SessionKey: SessionKey },
dataType: "jsonp",
success: myAlerts
});
}
var lostSelectedPet = 0;
function myAlerts(data)
{
$("#alertsListMissingPets").empty();
$.mobile.loading( 'hide', { theme: "b", text: "Loading", textonly: false});
$.each(data, function(index) {
console.log(data[index].LostDate)
$("#alertsListMissingPets").append(" <li>"+ data[index].AnimalKey + " <span class=\"ui-li-count\">12</span></li>");
});
$("#alertsListMissingPets").listview('refresh');
}
$(document).on('click', '#alertsListMissingPets li a', function(){
localStorage.setItem("lostSelectedPet", $(this).attr('data-custom'));
editingId = $(this).attr('data-custom');
});
The json returned is like:
callback(
{
AnimalKey: "f152e1c6baca181d9f3ca1f18c91cc41f23fc122545d9c8bff9f4cb2ea449874",
LostDate: "11/06/2014 16:14:19",
FoundDate: "",
LostKey: "7560733274a7ca2ec43a85fcb9abd345fdc876acffac2b75ace7946035122fbd",
Resp: "OK"
}
)
However, this returns - It shows 5 items but theres only one result, the json above is the full response.
You are not looping over an array, you are looping over an object. You have 5 keys in the object, hence why there is 5 rows in the output.
Change the response to be an array.
callback(
[{ //<-- added [
AnimalKey: "f152e1c6baca181d9f3ca1f18c91cc41f23fc122545d9c8bff9f4cb2ea449874",
LostDate: "11/06/2014 16:14:19",
FoundDate: "",
LostKey: "7560733274a7ca2ec43a85fcb9abd345fdc876acffac2b75ace7946035122fbd",
Resp: "OK"
}] //<-- added ]
)

Backbone + kendoGrid, PUT not working

I'm trying to integrate kendoGrid on a Backbone View, this is my view code:
App.Views.UsersManager = Backbone.View.extend({
tagName: 'section',
id: 'users-manager',
className: 'tile',
template: Handlebars.compile($('#profile-usersManager-template').html()),
render: function () {
console.log('usersManager.render -> collection', this.collection);
var self = this;
this.$el.html(this.template());
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: '/users',
type: 'GET',
dataType: 'json'
},
update: {
url: '/users',
type: 'PUT',
dataType: 'json'
}
},
schema: {
data: 'data'
},
batch: true
});
this.$('table.users-manager').kendoGrid({
scrollable: false,
sortable: true,
dataSource: dataSource,
toolbar: ["save"],
editable: true,
navigatable: true,
// filterable: true,
});
return this;
}
});
The view render correctly, and the kendoGrid correctly GET my users data from my SlimPHP framework, but when i try to modify an element of the grid and hit the "Save Changes" button provided by "toolbar: ["save"]", nothing happens, even on my firebug console... there's no server communication at all.
I'm new on kendo (and Backbone also) development, maybe i'm failing something on the syntax? :stuck:
Update after Atanas Korchev answer
this is my DataSource updated:
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: '/users',
type: 'GET',
dataType: 'json'
},
update: {
url: '/users',
type: 'PUT',
dataType: 'json'
}
},
schema: {
data: 'data',
model: {
id: 'id',
fields: {
email: {},
name: {},
surname: {},
rank: {},
type: {}
}
}
},
batch: true
});
That not solve my issue, i wanna notice that my php code look like that actually:
$app->put('/users', function () use ($app, $db) {
exit('put ok');
});
Just to see if the client/server communication works... I know it will be an error, but I can't see any firebug error too, like the "Save Changes" button has no event... (I will try the Dennis Rongo suggestion.. but I dont think is the solution...)
Sorry for my bad english
Try describing your model in the DataSource settings:
schema: {
data: 'data',
model: {
id: "MyId"
}
}
You need to at least specify the id.
Solved by removing the data: 'data' from the schema object, there's the link kendoGrid batch editing!

Categories