Kendo serverPaging using javascript and web API - javascript

I have been having some issues getting the serverPaging option to work on kendoGrid. I have searched for several hours and just can't seem to get it work the way I expect it to. Here is what I have:
API Call:
[HTTPGet]
[Route("GetItemsByPage", Name = "GetItemsByPage"]
public IEnumerable<IItem> GetByPage(int id, int page, int pageSize)
{
return foo.GetByPage(id, page, pageSize);
}
JS:
var sharedDatasource = new kendo.data.Datasource({
transport: {
read: {
url: "localhost:2222/api/product/Items/GetByPage/?id=38&page=1&pageSize=100"
dataType: "json"
}
},
schema: {
total: // function to return total //
// rest of schema info //
},
page: 1,
pageSize: 100,
serverPaging: true
});
I then have the datasource attached to a grid div (all that shows up fine). It is just the server paging I have an issue with. I can use another api call to get all items, and then allow local paging, but I dont want to get all that data at once.

You should setup transport.parameterMap option on your DataSource
var sharedDatasource = new kendo.data.Datasource({
transport: {
read: {
url: "localhost:2222/api/product/Items/GetByPage/?id=38&page=1&pageSize=100"
dataType: "json"
},
parameterMap: function(data, type) {
if (type == "read") {
// send take as "$top" and skip as "$skip"
return {
pageSize: data.pageSize,
page: data.page
}
}
}
},
page: 1,
pageSize: 100,
serverPaging: true
});
I don't know what is id in your code. But I hope you catch this idea.

Related

Navigating between Kendo Pages by using ID and showing data

I have 2 views in my MVC project From the View1 I am taking an ID and passing it to View2. On view2, I already have KendoGrid and I have controller that reads all data for me and display in grid.
My question is how to get data from ID in View2? I copied my script code of View2 below
var crudServiceBaseUrl = "http://localhost:23355/",
dataSource = new kendo.data.DataSource({
transport: {
read: {
type: "GET",
url: crudServiceBaseUrl + "/api/SpecificationDetails",
dataType: "json",
cache: false
},
update: {
// update code goes here
},
},
destroy: {
// delete code goes here
},
create: {
// create code goes here
},
parameterMap: function (options, operation) {
console.log(operation + '-' + options.models);
if (operation === "create" && options.models) {
options.models[0].SpexHeaderId = 5;
var jsonstr = JSON.stringify(options.models[0])
console.log(jsonstr);
return jsonstr;
}
else if (operation === "update" && options.models) {
var jsonstr = JSON.stringify(options.models[0])
console.log(jsonstr);
return jsonstr;
}
else if (operation !== "read" && options.models) {
return { models: kendo.stringify(options.models) };
}
}
},
batch: true,
pageSize: 4,
schema: {
model: {
id: "SpecificationDetailId",
fields: {
SpecificationDetailId: { editable: false, type: "number" },
DescriptionTitle: "DescriptionTitle",
Description: "Description",
}
},
total: function (response) {
return response.total;
}
}
});
You are running jQuery 1.5.
Kendo UI requires a minimum of jQuery 1.7.1 (for Kendo UI 2011.3.1129). The current official version of Kendo UI (2017.2.504 (R2 2017)) requires jQuery 1.12.3.
Please refer to this chart for the specific version of jQuery that you require for your version of Kendo UI. You can grab a link to any version of jQuery from code.jquery.com.
If you are using legacy code, you'll additionally need to include jQuery Migrate.
Hope this helps! :)

Data not populating the table created using jsgrid

I'm using jsgrid to create an editable table. i used the code from this demo. The only difference is im using mvc instead of web api.
Looking at the network, the controller returns the needed json data and jsgrid also shows the pagination stuff on the bottom of the table. However, the table is not being populated
Here's the html and javascript code
<div id="jsGrid"></div>
#section scripts {
<script src="http://js-grid.com/js/jsgrid.min.js"></script>
<script>
$("#jsGrid").jsGrid({
height: "50%",
width: "100%",
filtering: true,
inserting: true,
editing: true,
sorting: true,
paging: true,
autoload: true,
pageSize: 10,
pageButtonCount: 5,
deleteConfirm: "Do you really want to delete client?",
controller: {
loadData: function (filter) {
return $.ajax({
type: "GET",
url: "get",
data: filter,
dataType: "json"
});
},
insertItem: function (item) {
},
updateItem: function (item) {
},
deleteItem: function (item) {
}
},
fields: [
{ name: "SKU", type: "text", width: 50 },
{ name: "PartNumber", type: "text", width: 100 },
{ name: "ProductLineName", type: "text", width: 50 },
{ name: "ProductLineId", type: "text", width: 50 },
{ name: "Deleted", type: "checkbox", sorting: false },
{ type: "control" }
]
});
</script>
Here's the relevant method in the controller
public async Task<ActionResult> Get()
{
var query = db.Products
.Select(p => new ProductDto()
{
PartNumber = p.PartNumber,
SKU = p.SKU,
ProductLineName = p.ProductLines.ProductLineName,
ProductLineId = p.ProductLineId,
Deleted = p.Deleted
});
var products = await query.ToListAsync();
return Json(products, JsonRequestBehavior.AllowGet);
}
Anyone know what i can do to display/bind the returned data to the table?
Change your loadData call because its not specifying what to do when ajax call is done.
Try to rewrite it like below :
controller: {
loadData: function() {
var d = $.Deferred();
$.ajax({
url: "get",
dataType: "json",
data: filter
}).done(function(response) {
d.resolve(response.value);
});
return d.promise();
}
},
This is the client side javascript that I used which finally put some data in the grid: (just the controller part)
controller: {
loadData: function (filter) {
console.log("1. loadData");
return $.ajax({
type: "GET",
url: "/Timesheet/GetTimesheet/",
dataType: "json",
data: filter
console.log("3. loadData complete");
}
None of the posted explicit promise code functioned at all. Apparently $.ajax returns a promise.
and this was my MVC controller code that I called with ajax (C#):
public async Task<ActionResult> GetTimesheet()
{
int id = Convert.ToInt32(Session["UID"]);
var tl = (
from ts in db.Tasks
orderby ts.Task_Date descending
where ts.Emp_ID == id
select new
{
ID = ts.Task_ID,
Date = ts.Task_Date,
Client = ts.Customer_ID,
Hours = ts.Total_Hours
}
).Take(4);
var jsonData = await tl.ToListAsync();
return Json(jsonData, JsonRequestBehavior.AllowGet);
}
There are no actual examples of required Json for jsGrid. anywhere but this worked for me - note no headers or anything.

Properly Initialize Client Side Model

My issue is very simple. I am using ASP Web API, Entity Framework, Angular, and Kendo UI. I have 2 classes, FREQUENCY and FREQ_TYPE_. Class FREQUENCY has a navigation property to class FREQ_TYPE. I have a kendo ui grid that loads 10 class FREQUENCY models. Each class FREQUENCY model has it's FREQ_TYPE data loaded properly. My problem is that when I create a new row in my kendo ui grid and try to save the row to the server, I get an error saying the navigation property FREQ_TYPE needs to be initialized. This is expected of course since kendo doesn't know how to auto=initialize my nav properties.
What is the best practice for giving my angular JS client the knowledge it needs to create a new class FREQ_TYPE so I can properly initialize class FREQUENCY and save it to the server? My models only exist as code-first entity models, so I can't just create a new model in my client side JS as it doesn't know about these models. Is there some framework that can generate local model classes from an EF database? Or do I just have to manually set all the json fields for my class FREQ_TYPE navigation property? Or is there an easier way for me to use Web API so that I can make a request to "figure out" what the model info is and create a client side JS model without needing to have a "local model"?
Here is the client side grid and datasource:
$(document).ready(function () {
var crudServiceBaseUrl = "http://localhost:29858/";
var NIICDDS = new kendo.data.DataSource({
transport: {
read: {
url: crudServiceBaseUrl + "api/NIICDFreq",
dataType: "json"
},
update: {
url: function (data) {
console.log("DATA TEST");
console.log(data);
return crudServiceBaseUrl + "api/NIICDFreq/";
},
// url: crudServiceBaseUrl + "api/VHFMasterLists",
dataType: "json",
data: function (data) {
console.log("returning data in update TEST");
console.log(data.models[0]);
return data.models[0];
},
type: "PUT",
contentType: "application/json; charset=utf-8",
},
destroy: {
url: crudServiceBaseUrl + "api/NIICDFreq",
dataType: "json"
},
create: {
url: crudServiceBaseUrl + "api/NIICDFreq",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8"
},
parameterMap: function (model, operation) {
if (operation !== "read" && model) {
return kendo.stringify(model);
} else {
return kendo.stringify(model) ;
}
}
},
batch: true,
pageSize: 20,
schema: {
data: function (data) { //specify the array that contains the data
console.log("DATA RETURN TEST");
console.log(data);
return data || [];
},
model: {
id: "Id",
fields: {
Id: { editable: false,
nullable: false,
type: "number"
},
Frequency: { type: "string" }
}
}
}
});
$("#NIICDFreqGrid").kendoGrid({
dataSource: NIICDDS,
columns: [
{ field: "Id", title: "Freq ID", format: "{0:c}", width: "120px" },
{ field: "Frequency", title: "Frequency Test", format: "{0:c}", width: "120px" },
{ command: ["edit", "destroy"], title: " ", width: "250px" }
],
toolbar: ["create"],
editable: "inline"
});
});
And here is the web api controller:
[ResponseType(typeof(FREQUENCY))]
public IHttpActionResult PostFREQUENCY(FREQUENCY testfreq)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.FREQUENCIES.Add(testfreq);
try
{
db.SaveChanges();
}
catch (DbUpdateException)
{
if (FREQUENCYExists(testfreq.Id))
{
return Conflict();
}
else
{
throw;
}
}
return CreatedAtRoute("DefaultApi", new { id = testfreq.Id }, testfreq);
}
The error is the last line:
iisexpress.exe Information: 0 : Request, Method=POST, Url=http://localhost:29858/api/NIICDFreq, Message='http://localhost:29858/api/NIICDFreq'
iisexpress.exe Information: 0 : Message='NIICDFreq', Operation=DefaultHttpControllerSelector.SelectController
iisexpress.exe Information: 0 : Message='CFETSWebAPI.Controllers.Frequency.NIICDFreqController', Operation=DefaultHttpControllerActivator.Create
iisexpress.exe Information: 0 : Message='CFETSWebAPI.Controllers.Frequency.NIICDFreqController', Operation=HttpControllerDescriptor.CreateController
iisexpress.exe Information: 0 : Message='Selected action 'PostFREQUENCY(FREQUENCY testfreq)'', Operation=ApiControllerActionSelector.SelectAction
iisexpress.exe Information: 0 : Message='Value read='DomainModelModule.FREQUENCY'', Operation=JsonMediaTypeFormatter.ReadFromStreamAsync
iisexpress.exe Information: 0 : Message='Parameter 'testfreq' bound to the value 'DomainModelModule.FREQUENCY'', Operation=FormatterParameterBinding.ExecuteBindingAsync
iisexpress.exe Information: 0 : Message='Model state is invalid.
testfreq.FREQ_POOL: The FREQ_POOL field is required.,testfreq.FREQ_TYPE: The FREQ_TYPE field is required.', Operation=HttpActionBinding.ExecuteBindingAsync
And of course testfreq has all null values.
Thank you for your help.
Since you shared no code, I can only make an assumption. However, I think you're confused with the error message. Neither Kendo or Angular are responsible. They do not "initialize" classes. You said yourself, the data is there on the client.
From what it sounds like to me, the data arrives at your controller action, and the compiler does not know how to initialize your class. Make sure your Class B has a constructor defined in your server-side code. Even an empty constructor will suffice, unless the members of the class need explicit initialization themselves.
public class B {
// constructor
public B() {
// initialize class members
}
}

Kendo Grid C# - Select current page without refresh datasource again

i have been trying to fix this, what i want to do is:
I have a datasource who gets data from server, when i go to server, i get the list of items, then i have to search the item i have to select (This item could be in any page), after i have the item and the page where the item is located (assuming each page has 30 items), then i call LINQ expression to skip the required ammount of data and take 30. Finally i return this list to the client side.
When data arrives to client i need to "auto-select" the selected item and change the page to locate the user in the right page where the selected item is located. I have the new page, skip, selected value and everything in the client side again.
What do you suggest to me to change the page into the kendo grid datasource without call a new refresh and go to the server again?
This is how the datasource looks like:
return new kendo.data.DataSource({
serverPaging: true,
transport: {
read: {
url: URLController.Current().getURL('MyURL'),
contentType: 'application/json',
accepts: 'application/json',
type: 'POST'
},
parameterMap: function(data, type) {
if (data) {
return JSON.stringify(
{
data: jsonData,
pageSize: data.pageSize,
skip: data.skip,
take: data.take
});
}
}
},
schema: {
data: function (data) {
var dropDownData = JSON.parse(data);
gridElement.attr('data-model', JSON.stringify({ data: data }));
return dropDownData.Data;
},
total: function (data) {
var dropDownData = JSON.parse(data);
return dropDownData.total;
},
model: {
id: 'ID'
}
},
pageable: true,
pageSize: 30,
error: function(e) {
alert('Error ' + e);
}
});
When the grid data is bounded i have to change the page to current page number and then select the current item.
grid.one('dataBound', function (e) {
var currentGridElement = this.element;
var currentModel = currentGridElement.attr('data-model');
var currentJsonData = parseDropDownDataJSONString(currentModel).data;
var gridDataSource = this.dataSource;
var selection = gridDataSource.get(currentJsonData.selectedValue);
if (selection != undefined) {
var row = currentGridElement.find('tbody>tr[data-uid=' + selection.uid + ']');
if (row != undefined) {
currentGridElement.attr('data-closeByChange', false);
gridDataSource.page(currentJsonData.pageNumber);
this.select(row);
dexonDropDownGrid.combobox().text(selection.DISPLAY);
}
}
var aaaa = 0;
});
This is how my databound event listener looks like, when i try to set the page it calls again the server and i got more delay to load the right data.
Is there any way to solve this?
Thanks
Have the same problem.
There is how I fix that(not the best solution ever, but it works):
var forcedPageChange = false;
var cachedResult;
var dataSource = new kendo.data.DataSource({
transport: {
read: function (options) {
if (forcedPageChange) { // prevent data request after manual page change
forcedPageChange = false;
options.success(cachedResult);
cachedResult = null;
return;
}
gridDataProvider.getData() // promise of data
.then(function (result) {
// check if current page number was changed
if ($scope.gridConfig.dataSource.page() !== result.pageNumber ||
$scope.gridConfig.dataSource.pageSize() !== result.rowsPerPage) {
cachedResult = _.clone(result);
forcedPageChange = true;
options.page = result.pageNumber;
options.pageSize = result.rowsPerPage;
$scope.gridConfig.dataSource.query(options);
}
options.success(result);
}, function () {
options.error();
});
}
},
schema: {
data: function (response) {
return response.items;
},
total: function (response) {
return response.totalCount;
}
},
//...
serverPaging: true,
serverSorting: true,
serverFiltering: true
});
I found that dataSource.page(newPageNumber) doesn't work in this situation. It just drop page number to 1.
This solution works, but I still have a bug with missing sorting icon after dataSource.query(options)...

Kendo Grid CRUD: how make update

i have a kendo ui grid with asp web api as backend. When i call the create method in the kendo ui, it's called the following method in web api
public IHttpActionResult PostProduct(ProductDTO product)
{
...
...
return StatusCode(HttpStatusCode.NoContent);
}
Now if i try to edit the item in the Kendo Ui Grid is called again the create method instead of the update method.
If i reload the page (so is called the read method of kendo ui grid), the update method works.
What's the problem? I have the following schema:
schema: {
model: {
id: "Id",
fields: {
Id: { editable: false, type: "number" },
Name: { validation: { required: true } },
Description: { editable: true },
Price: { editable: true },
Active: { type: "boolean" },
}
}
}
I have the following transport (omitted some code)
$scope.tabellaProdotto = new kendo.data.DataSource({
transport: {
read: {
url: function () {
return "api/Prodotti/GetProdottoPerTipoProdotto/" + productTypeMainSelected;
},
dataType: "json"
},
create: {
url: "api/Prodotti/PostProdotto",
dataType: "json",
data: function (prodottoTmp) {
...
},
type: "POST"
},
update: {
url: function (prodotto) {
return "api/Prodotti/PutProdotto" + prodotto.Id
},
data: function (prodottoTmp) {
...
},
type: "PUT",
dataType: "json"
UPDATE: the problem seems be the return of the web api action method:
return CreatedAtRoute("DefaultApi", new { id = p.Id }, p);
Now works but the p object size dimension is very high: i must return the entire object?
This sounds like the Grid is not getting the Json back in the right format.
Be sure to use the KendoMVC DataSourceRequest Object to return data in the right format.
Here is an example:
public ActionResult Update([DataSourceRequest] DataSourceRequest request, MyViewModel data)
{
var result = UpdateBackend(data);
return Json(result.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}

Categories

Resources