Kendo UI Grid - Excel like filtering - kendo-ui

In the new version of Telerik Kendo UI, the multi-select checkboxes option as part of the filtering menu was introduced.
My question is if there is a way to display the elements in the multi-select list sorted in a given way.
The filter is set like this:
filterable: {
multi: true,
dataSource: {
transport: {
read: {
url: apiUrl,
dataType: "json"
}
},
schema: {
data: "data",
error: "error"
},
}
}
Another problem si that, if the columnMenu is set to active, the filtering is not working (it doesn't make any request to the server).

Have you tried using the sort options on the DataSource? It should allow you to sort by any field ascending or descending, or add a custom sorting function.
For example:
filterable: {
multi: true,
dataSource: {
transport: {
read: {
url: apiUrl,
dataType: "json"
}
},
schema: {
data: "data",
error: "error"
},
sort: {
field: "name",
dir: "asc"
}
}
}

Related

How to parse my JSON data to String in KENDO GRID?

how can i format this object Object to its actual values ?
I want this json object to display its actual values in a specific kendo grid column .
Can someone please help me and teach me how to do it ?
This is the image of the kendo grid with the result ,
While here is the code that I am using in my view .
Can please someone help .
contact : new kendo.data.DataSource({
transport:{
read:{
type: "GET",
url:"reservation/list",
dataType:"json",
contentType: "application/json; chartset=utf-8"
},
update: {
url: "contacts/update",
dataType: "json",
type: "POST"
},
destroy: {
url: "contacts/destroy",
dataType: "json",
type:"POST"
},
create: {
url: "contacts/store",
dataType: "json",
type:"POST"
}
},
schema:{
model:{
id:"id",
fields:{
Purpose:
{
type:"string",
validation:{required:true}
},
RoomID:
{
from: "RoomID.room_name",
type: "string"
},
Equipments:
{
from: "Equipments",
type: "string"
},
start:
{
type:"date",
validation:{required:true}
},
end:
{
type:"date",
validation:{required:true}
},
}
}
},
pageSize:10
}),
init : function(e){
$("#grid").kendoGrid({
dataSource: this.contact,
selectable: true,
height:600,
editable: "popup",
filterable: true,
sortable: {
mode: "multiple",
allowUnsort: true,
showIndexes: true
},
toolbar: ["search"],
columns: [
{
field: "Purpose",
title:"Purpose"
},
{
field: "RoomID",
title:"Room",
},
{
field: "Equipments",
title:"Equipments",
},
{
field: "start",
title:"Start",
//template: '#= kendo.toString(kendo.parseDate(start), "MM/dd/yyyy HH:mm:ss")#'
format: "{0:MMM dd,yyyy hh:mm tt}",
parseFormats: ["yyyy-MM-dd'T'HH:mm.zz"]
},
{
field: "end",
title:"End",
//template: '#= kendo.toString(kendo.parseDate(end), "MM/dd/yyyy HH:mm:ss")#'
format: "{0:MMM dd,yyyy hh:mm tt}",
parseFormats: ["yyyy-MM-dd'T'HH:mm.zz"]
},
{
command: ["edit", "destroy"],
title: " ",
width: "250px"
}
],
pageable:{
pageSize:10,
refresh:true,
buttonCount:5,
messages:{
display:"{0}-{1}of{2}"
}
}
});
},
});
kendo.bind($("#whole"),model);
model.init();
Hopefully this will help you out with templating out the results.
https://dojo.telerik.com/ICOceLUj
In the example above I have created a custom column that takes the incoming row object and then parsed the name of the item and the category object into a single template.
To achieve this I have added the template property and used a function with an external template script to handle the manipulation. I personally find this easier to manage than trying to inline a complex client template (especially if you have logic involved)
So this is how we set it up initially:
{ title: "custom template", template:"#=customTemplate(data)#" }
obviously you will change it to the property you need to look at in your model.
then the function is a couple of lines of code:
function customTemplate(data){
var template = kendo.template($('#customTemplate').html());
var result = template(data);
return result;
}
so this takes the customTemplate template i have created for this and renders it as html and then it will apply the data where appropriate. The template looks like this:
<script id="customTemplate" type="text/x-kendo-template">
<div>
<h5> #:data.ProductName#</h5>
<h4>#: JSON.stringify(data.Category, null, 4) #</h4>
</div>
</script>
You can then customize this template to how you need it to look for your specific needs. You can then either create a source template for the items and then map the values back as single string or have the logic for this in the template. Which ever is most sensible in your case.
For more info on templating please look at this link:
https://docs.telerik.com/kendo-ui/framework/templates/overview
You can use kendo.stringify in your column template.
Example:
kendo.stringify(YourProperty)

Bind Kendo Grid data with dropdown value

I have kendo dropdownlist on page which is fetching results from database as below. I also have a grid at the same page at same time which needs kendo dropdownlist value i.e the value from years dropdownlist but I am unable to get it at the same time.This is how I am following. Where I am doing wrong.
<script type="text/javascript">
var GridUrl;
$("#Years").kendoDropDownList({
dataTextField: "Name",
dataValueField: "Id",
dataSource: {
transport: {
read: {
dataType: "json",
url: "../../Service/GetYears"
}
}
}
});
$(document).ready(function () {
BindGridData();
GridUrl = '#Url.Action("Read", "Home")';
});
function BindGridData()
{
GridDataSource = new kendo.data.DataSource({
type: "aspnetmvc-ajax",
serverFiltering: true,
serverPaging: true,
serverSorting: true,
pageSize: 10,
transport: {
read: {
url: GridUrl,
data: { year: $('#Years').val() }
}
},
schema: {
data: "Data", total: "Total"
}
});
}
Changing line to this
year: $('#Years').data("kendoDropDownList").value()
should do a trick. You need to get instance of kendoDropDownListwidget in order to get its value. You need to do so, because kendoDropDownListwidget value is not saved directly into html element
First of all, you need to move the initialisation of the kendoDropDownList inside the document ready function. If you don't you may end up refering to elements that are not loaded (yet).
The second change that should be done is how you get the value from the kendoDropDownList. Usually, you should refer to the widget instead of the DOM element: $('#Years').data("kendoDropDownList").value()
Finally, you didn't mention how and when your grid was binded but you may want to refresh the grid data if the user change the dropdown value. If it's the case, you may want to use change event of the dropdown to refresh the grid data.
$(document).ready(function () {
$("#Years").kendoDropDownList({
dataTextField: "Name",
dataValueField: "Id",
dataSource: {
transport: {
read: {
dataType: "json",
url: "../../Service/GetYears"
}
}
},
change: function(e) {
$("#YourGrid").data("kendoGrid").dataSource.read();
}
});
BindGridData();
GridUrl = '#Url.Action("Read", "Home")';
});
function BindGridData() {
GridDataSource = new kendo.data.DataSource({
type: "aspnetmvc-ajax",
serverFiltering: true,
serverPaging: true,
serverSorting: true,
pageSize: 10,
transport: {
read: {
url: GridUrl,
data: { year: $('#Years').data("kendoDropDownList").value() }
}
},
schema: {
data: "Data", total: "Total"
}
});
}

Grid remote data virtualization with custom transport.read method?

I would like to use the Kendo grid with remote data virtualization. I also need to have a custom method for the transport.read property.
My grid is configured like this:
$(document).ready(function () {
$("#grid").kendoGrid({
dataSource: {
serverPaging: true,
serverSorting: true,
pageSize: 100,
transport: {
read: function (options) {
// Get the template items, which could be products, collections, blogs or articles
getTemplateItems().then(function (data) {
options.success(data);
});
}
}
},
schema: {
total: function(response) {
return 2000;
}
},
height: 543,
scrollable: {
virtual: true
},
sortable: true,
columns: [
{ field: "title", title: "Title" }
]
});
});
function getTemplateItems() {
var deferred = $q.defer();
smartseoEntityMapping.getEntityInfo({ mappedEntityType: mappedEntityType.Product }).$promise.then(function (data) {
deferred.resolve(data);
});
return deferred.promise;
}
The problem is that the read method is only called once when the grid is initialized. It is not called when the scroll reaches the last item in the current visible set.
I suspect that the grid needs the total number of items but I cannot understand how to set the total number of items. Setting a method for the schema.total property does not work because the method is never called.
So I would like to ask you, is this scenario possible at all, to have the virtualization work with a custom transport.read method, which needs to be called every time to get the next page of data?
Why I am using a custom read? Well I cannot just set an url for the transport.read property because my remote call is made via an angularjs resource, involves setting authentication, etc...
schema is a property of a kendo datasource. It looks like you have it outside of the datasource.
Should be:
$("#grid").kendoGrid({
dataSource: {
serverPaging: true,
serverSorting: true,
pageSize: 100,
transport: {
read: function (options) {
// Get the template items, which could be products, collections, blogs or articles
getTemplateItems().then(function (data) {
options.success(data);
});
}
},
schema: {
total: function(response) {
return 2000;
}
}
},
height: 543,
scrollable: {
virtual: true
},
sortable: true,
columns: [
{ field: "title", title: "Title" }
]
});

Kendo Grid renders properly but does not display json data

I have been having a tough time with grids lately, mostly getting them to display properly formatted JSON data that is being fetched from a webservice (which has been checked in VS2013, and JSONLint), if a second set of eyes could please have a look at my solution and tell me whats lacking? I am going bananas!
function SetTelerikGrid() {
// prepare the data object and consume data from web service,...
$.ajax({
type: "GET",
async: false,
url: "http://localhost:38312/SDMSService.svc/GetProductPositionsByLocation/0544",
datatype: "json",
success: function (ProductData, textStatus, jqXHR) {
// populate kendo location grid by data from successful ajax call,...
$("#LocationProductsGrid").kendoGrid({
dataSource: {
data: ProductData, // solution here was: **JSON.parse(LocationData)**
schema: {
model: {
fields: {
Date: { type: "string" },
ProductCode: { type: "string" },
StoreNum: { type: "string" },
ProductQty: { type: "int" }
}
}
},
pageSize: 20
},
height: 550,
scrollable: true,
sortable: true,
filterable: true,
pageable: {
input: true,
numeric: false
},
columns: [
{ field: "Date", title: "Date", width: "130px" },
{ field: "ProductCode", title: "Product Code", width: "130px" },
{ field: "StoreNum", title: "Store Number", width: "130px" },
{ field: "ProductQty", title: "Product Qty", width: "130px" }
]
});
}
});
}
There is a breaking change in ASP.NET Core, related to how the JSON serializer
works
You can probably mitigate this by adding a json option like this:
1:
change
services.AddMvc();
to
services
.AddMvc()
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
OR
2:
public IActionResult Read()
{
// Override serializer settings per-action
return Json(
MyModel,
new JsonSerializerSettings { ContractResolver = new DefaultContractResolver() }
);
}
refrences :
http://www.telerik.com/forums/using-2016-2-630-preview---data-not-displayed#qlHR6zhqhkqLZWuHfdUDpA
https://github.com/telerik/kendo-ui-core/issues/1856#issuecomment-229874309
https://github.com/telerik/kendo-ui-core/issues/1856#issuecomment-230450923
Finally figured it out, the 'ProductData' field - although in perfect JSON format - still required to be parsed as JSON in the datasource configuration, like so,...
Data: JSON.parse(ProductData)

Get all updated and newly created models together in a single url in server side

I am Using Kendo grid with batch edit. I want to get all Modified and newly created models together in a single url.
Say I have created 3 new row and also updated/edited 2 existing row in grid. Data source makes a HTTP request for every CRUD operation . The changed data items are sent by default as models and hit URL as I declared in “create” and update (transport) section of transport in datasource.I am getting models those are Modified (updated) in URL declared for ‘update’ in server side. And also find models those are newly created in URL declared for ‘create’….But I want to get all Modified and newly created models together in a single url.Is it possible to get all of the (both all modified and newly created) in a single URL?
Here is my Code for better understand.
$("#grid").kendoGrid({
dataSource: {
transport: {
read: {
url: "LoadPerMeterCostsGridData",
type: "POST",
contentType: "application/json",
dataType: "json"
},
update: {
url: "UpdatePerMeterCostsData",
contentType: "application/json",
type: "POST",
dataType: "json"
},
create: {
url: "CreatePerMeterCostsData",
contentType: "application/json",
type: "POST",
dataType: "json",
},
parameterMap: function (data, operation) {
if (operation != "read") {
return kendo.stringify(data.models);
}
}
},
serverPaging: false,
pageSize: 10,
batch: true,
schema: {
model: {
id: "PerMeterCostID",
fields: {
PerMeterCostID: { editable: false },
DrillBitSizeID: { editable: true },
Form: { editable: true },
To: { editable: true },
PerMeterCost: { editable: true },
ContractID: { editable: false }
}
},
errors: "Errors"
},
error: function (e) {
alert(e.errors + "grid");
}
},
editable: true,
pageable: {
refresh: true,
pageSizes: true
},
toolbar: ["create",
"save",
"cancel"
],
sortable: true,
autoBind: false,
columns:
[
{ field: "PerMeterCostID", width: 50, hidden: true, title: "ID" },
{ field: "DrillBitSizeID", width: 100, hidden: true, title: "Consumable" },
{ field: "Form", width: 100, title: " Form " },
{ field: "To", width: 50, title: "To" },
{ field: "PerMeterCost", width: 100, title: "Per Meter Cost" },
{ field: "ContractID", width: 100, hidden: true, title: "ContractID" },
{ command: ["destroy"], title: "Action", width: "175px" }
]
});
$("#grid ").data("kendoGrid").dataSource.read();
You can set each CRUD action to use the same url, but using the same url: property for both Create and Update. However you will still minimally get TWO requests (albeit to the same url)
update: {
url: "UpdateOrCreateAction",
},
create: {
url: "UpdateOrCreateAction",
},
this is because internally the dataSource pushes all "new" items as defined by "items an Id Field set to the default value for the field" in an array, and all items with dirty set to true into a different array. Kendo then sends both arrays back to the server according to the url for the action. (something like this i'd imagine)
if ( model.isNew())
createdPile.push(model)
else if ( model.dirty === true)
updatedPile.push(model)
//send both piles to the server
The "easiest" way to avoid this is to make sure your new objects explicitly set their id fields to something other then the default, and set the models dirty prob to true.
you could do this by using the edit event to override the actions
grid.bind('edit', function(e){
if ( e.model.isNew() ) {
e.model.id = -1; //
e.dirty = true;
console.log(e.model.isNew()) // should be false
}
})
this is probably an extreme amount of overkill to avoid one additional request, and prone to error. I would advise that you use the same url for both actions, and just accept that you will get the created items in one batch, and the updated in another.

Resources