Creating a column in KendoGrid that is not bound to datasource - kendo-ui

I am using Kendo UI to bind a datasource to the Kendo Grid. I am trying to find the best way to create a column in the grid that is not bound to the datasource.
Currently, I am creating a field in the datasource and using some javascript and jQuery to set the values of that column after the data is read from the remote endpoint.
Datasource:
schema: {
model: {
fields: {
blah: {},
empty_column: {}
}
}
}
Grid:
columns: {
field: "empty_column",
width: 100,
title: "Empty"
}
Javascript:
datasource.data[item].set("empty_column", computed_value);
All code edited for brevity, it all works fine.
My question: is there a way to set the defaultValue for this new, empty column which is not connected to the remote endpoint?
When I set:
empty_column: {defaultValue: "None"}
the grid still displays 'undefined', I think because it is not receiveing any data for that field in the read operation. Is there a way to set the defaultValue in the grid? I haven't seen any examples of this...

defaultValue applies when you create a record, not when it is going to be displayed.
You can do:
Option 1: use parse in schema.fields.fieldName that would be something like this.
model: {
fields: {
empty_column: {
type : "string",
defaultValue: "none",
parse : function (data) {
if (!data.empty_columns) {
data.empty_column = "none";
}
return data;
}
},
blah : { type: "number" }
}
},
Option 2: Use schema.parse for adding the extra field value.
schema: {
model: {
fields: {
empty_column: {type: "string", defaultValue: "none"},
blah : { type: "number" }
}
},
parse: function (response) {
$.each(response, function (idx, item) {
if (!item.empty_column) {
item.empty_column = "none";
}
});
return response;
}
}
Of course, (for both options) if you certainly know that there is no previous value in empty_column you might save the test condition and leave only the assignment.

Related

How to modify csv data in amcharts export

I want to modify csv data while export from amcharts.
Scenario is like : I have 2 column 1 with values and other with 0. Now i dont want that column to display in the csv which have 0 values.
I did not find anything for this.
You could use processData for that. See more here: https://github.com/amcharts/export#changing-the-dataprovider-when-exporting
"export": {
"enabled": true,
"processData": function (data, cfg) {
if (cfg.format === 'CSV') {
return data.map(function (item) {
// Ignore the second column
return {
firstColumn: item.firstColumn
};
});
}
return data;
}
}
The processData way is fine for datas that do not much differ to the dataProvider.
Amcharts's doc is not very well documented about this, but after a bit of digging, I found this way :
var myChart = AmCharts.makeChart('chart-id', {
dataProvider: myDatas, // Some datas
export: {
enabled: true,
// Using the 'menu' option in order to override its behavior ...
menu: [{
class: 'export-main',
menu: [{
label: 'Download as ...',
menu: ['PNG', 'JPG', 'SVG', 'PDF']
}, {
label: 'Save as ...',
menu: [{
label: 'CSV',
// Overriding CSV export behavior :
click: function exportCSV() {
// This will export the 'myDatas' datas to a string formatted as a CSV.
// Feel free to change the 'data' option of the 'toCSV()' method for a different CSV.
myChart.export.toCSV({ data: myDatas }, function(data) {
// 'data' is a string containing the CSV
// This will download the CSV to the file MyCSV.csv !
this.download(data, this.defaults.formats.CSV.mimeType, 'MyCSV.csv');
});
}
}]
}, {
label: 'Annotate ...',
action: 'draw',
menu: [{
class: 'export-drawing',
menu: ['PNG', 'JPG']
}]
}]
}]
}
});
This will export and download a CSV file with the desired datas !

Kendo Grid showing all records even when page size is defined

I'm new to kendo UI, I am trying to implement Kendo grid with Webapi, paging does not take any effect below is the code.
The API
public IList<Customer> GetCustomers(int take, int skip)
{
this.Customers = FillData.Customers;
this.Orders = FillData.Orders;
return Customers.Skip(skip).Take(take).ToList();
}
And the javascript
$(document).ready(function () {
var element = $("#grid").kendoGrid({
dataSource: {
type: "json",
transport: {
read: "/api/GridData/GetCustomers",
dataType: "json"
},
pageSize: 6,
serverPaging: true,
},
height: 600,
sortable: true,
pageable: true,
//detailInit: detailInit,
//dataBound: function () {
// this.expandRow(this.tbody.find("tr.k-master-row").first());
//},
columns: [
{
field: "FirstName",
title: "First Name",
width: "110px"
},
{
field: "LastName",
title: "Last Name",
width: "110px"
},
{
field: "Country",
width: "110px"
},
{
field: "City",
width: "110px"
},
{
field: "Title"
}
]
});
});
The same thing with the Odata service telerik has provided works well.
Well I wrote a blog post couple of months back - Kendo UI Grid - Server Side Paging, Filtering and Sorting. This should resolve your query. Major focus in the post is on sending the right parameters to the WebAPI. I have shown a sample grid and datasource code as well request and response objects sent to the WebAPI. Let me know if you need any explanations.
Edit: Posting it all here since link only is not appreciated.
The Grid
Below is a Kendo UI Grid declaration for which we will implement the server side manipulation.
$("#sampleGrid").kendoGrid({
columns: [
{ field: "ID", title: "ID", width: 50 },
{ field: "Label", title: "Label", template: "<span class='k-link bold' title='${Description}'>${Label}</span>" },
{ field: "Description", title: "Description" }
],
dataBound: function () { this.element.find('tbody tr:first').addClass('k-state-selected') },
pageable: {
refresh: true,
pageSizes: [10, 15, 20, 25]
},
resizable: true,
reorderable: true,
filterable: true,
groupable: true,
selectable: true,
sortable: true
});
The DataSource
The below DataSource sends a call to a server method, address to which is saved in svcSampleUrl and assigned to it in the "transport" property. There is no need to make an ajax call separately to fetch the data for the datasource,
Setting serverPaging, serverFiltering, and serverSorting as true enables the Kendo UI Grid DataSource to send server calls when any one of the following events are triggered by the user; change of page, change in filters, and change in sorting of a column.
var sampleDataSource = new kendo.data.DataSource({
transport: {
read: {
url: svcSampleUrl,
contentType: "application/json; charset=utf-8",
type: "POST",
dataType: "json"
},
parameterMap: function (options) {
model.Take = options.take;
model.Skip = options.skip;
model.Sort = options.sort;
model.Filter = options.filter;
return kendo.stringify(model);
}
},
schema: {
data: "sampleDTOList",
// another way to accept the response if some particular values need processing
//data: function (response) {
// //some implementation with the response values
// return response.WorklistDTOList;
//},
total: "totalItems",
model: {
fields: {
ID: { type: "number" },
Label: { type: "string" },
Description: { type: "string" }
}
}
},
serverPaging: true,
serverFiltering: true,
serverSorting: true,
pageSize: 10,
});
The parameter map property allows us to send a set of default parameters along with our custom ones back to the server. The default parameters include "take", "skip", "sort", and "filter" that correspond to page size, amount of records to skip, sort criteria, and filter criteria array respectively. Since one may require to send other parameters as well, the default parameter values are set in the model that has other values. Kendo.stringify is applied to the model and returned as a complete request object.
Data and Total
The DataSource schema contains two properties; "data" and "total". Each of these are the names of attributes in the response object in which we expect our results. I have assigned "sampleDTOList" to the "data" property since my response object will contain the list of records under that name. Similarly, I have assigned "totalItems" to "total" property. The "total" property accepts a numerical value of the count of all records irrespective of how many are returned on the current page. That way the DataSource knows how many records there are in actual and how many pages to show.
Note: The model is not explored here and is just referenced as a place holder for any model that can be used.
The Request
The Request object contains the exact attributes as the default and custom parameters the DataSource is set to send to the server.
public class FilterDTO
{
public int Take { get; set; }
public int Skip { get; set; }
public List<SortCriteria> Sort { get; set; }
public List<FilterCriteria> Filter { get; set; }
public string ID { get; set; }
}
public class SortCriteria
{
public string field { get; set; }
public string dir { get; set; }
}
public class FilterCriteria
{
public string field { get; set; }
public string operator { get; set; }
public string value { get; set; }
}
The Server End
This is where we receive the call with all the parameters needed to manipulate the data. This is a simple method that can call a database stored procedure with all the parameters for the filtered results. The stored procedure should then return a dataset according to the given page size, amount of records to skip, sort criteria, filter criteria array and any other filter parameter that me have been sent by the model included in the call request. Page number though requires to be calculated from the information we have.
[HttpPost]
[ActionName("GetItems")]
public SampleResponse GetItems(FilterDTO filterDTO)
{
//Calling a different layer for the read operation based in the parameter values
return BusinessLayer.GetItems(filterDTO);
}
Page Number
Since we receive "take" and "skip" from client end of the application, calculating required paged number is easy from the information given. When we know page size and amount of records to skip, we can obtain the page number by applying the following rule:
pageNo = (skip + take) / take
The Response
The Response object contains the two attributes needed by the DataSource as mentioned before; one for the "data" and one for the "total" property of the schema.
public class SampleResponse : BaseResponse
{
private List<SampleItems> SampleDTOList;
public List<SampleItems> sampleDTOList
{
get { return SampleDTOList; }
set { SampleDTOList = value; }
}
public int totalItems { get; set; }
}

Setting dataTextField value in Kendo UI kendoComboBox object

I have a Kendo UI combobox object something like this :
widget: "kendoComboBox",
options: {
dataTextField: "#:userFirstName#&nbsp#:userLastName#",
dataValueField: "userId",
template: "#:userFirstName#&nbsp#:userLastName#",
change: function (e) {
that.model.fn.bringUserData();
}
}
I can arrange the template, but i cannot dataTextField value depends on that template. It is possible to make it "userId" etc. But seems not possible to set selected value as #:userFirstName#&nbsp#:userLastName#. (dataTextFieldTemplate doesn't work.)
Could you help me to solve this?
Correct, you cannot make it a composition of two fields. It needs to be a field per se. What you can do is when reading data from the DataSource create an additional field that is the concatenation of those two fields. You can add to you DataSource definition something like this:
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: "..."
}
},
schema: {
parse: function(response) {
$.each(response, function(idx, elem) {
elem.fullName = elem.firstName + " " + elem.lastName;
});
return response;
}
}
});
Then the options for the combobox are simply:
options: {
dataTextField: "fullName",
dataValueField: "userId",
...
}
See it in action here : http://jsfiddle.net/OnaBai/12hpLeux/1/

How to filter kendo grid data using filter specified for computed column

Have a look at this jsfiddle
I have a computed column (NewCol as mentioned in the below code) in the kendo grid - which has filter option enabled. The columns shows True/False based on the data of the other column.
schema: {
model: {
fields: {
OrderID: { type: "number" },
Freight: { type: "number" },
OrderDate: { type: "date" },
ShipCity: { type: "string" },
NewCol: {type: "string"}
}
}
}
The column definition in grid is,
{
field: "NewCol",
title: "Computed",
template: '#= (OrderDate > new Date(1996,6,10) ) ? "False" : "True" #'
}
Now, my issue is, the data are not getting filtered using that column filter i.e. True/False. If I filter with True/False, the grid goes empty.
I have tried defining function in datasource for the column as below, but then its not showing any data for the column.
NewCol: function () {
console.log(this.get('OrderDate'));
if (this.get('OrderDate') > new Date()) return 'False';
else return 'True';
},
Ans shows the js error Uncaught TypeError: undefined is not a function
There are two options. The first is compatible with your version of KendoUI, the second you will have to move to current one.
1st solution, define a schema.parse function that computes the new column on read time:
parse: function (data) {
var tgtDate = new Date(1996,6,10);
$.each(data.d.results, function(idx, elem) {
var d = parseInt(elem.OrderDate.substr(6));
elem.NewCol = (d > tgtDate ) ? "False" : "True";
});
return data;
}
From there, the column is like any other column received from the server so you can use it.
You can see you JSFiddle modified here http://jsfiddle.net/OnaBai/3TsGB/3/
2nd solution is use a new feature that allows to define a options.fields.fieldName.parse function for a field definition in the model and do something similar to what I did in the previous solution.

Pass variable from kendo datasource to template

I am trying to pass a string from the kendo datasource, into a template within the grid, that is acting as the Print button. The button fires a function that opens a new link to the report server, and I need to pass a string value into the function, so that string value is then sent in the url.
I have it working if I send the datasource Id field, but if I try to send a string value (Physician), I get an 'Unexpected identifier' error. I have tried changing the coluns: field: to Physician, but get the same error.
EDIT: I can pass any int value, but it breaks if I try to send a string.
How do I pass a value other than the Id to my template?
schema: {
model: {
id: "Id",
fields: {
"ClinicName": { type: "string" },
"Physician": { type: "string" },
"Phone": { type: "string" },
"Fax": { type: "string" },
"Specialty": { type: "string" },
"Consent": { type: "date" }
}
}
},
pageSize: 10
});
function printForm(Physician) {
var stuid = $('#sisid').html().match(/\d+/);
var user = $('#user').val();
var sid = $('#sess').val();
window.open("http://#reportServer/ReportServer/Pages/ReportViewer.aspx?/SHPN/Treatment%20Form&rs:Command=Render&StudentId=" + stuid + "&SessionId=" + sid + "&CurrentUser=" + user + "&Physician=" + Physician);
};
$(document).ready(function () {
columns: [
{
field: "Id",
width: "38px",
title: "Print",
filterable: false,
sortable: false,
template: "<a class='change-image' href='javascript:void(0);' title='Print Treatment Form' onclick='printForm(#= Id #)'><img alt='Student Info' src='#Url.Content("~/Content/Images/printer-icon.png")' /></a>"
},
Since Physician is a string you are probably not correctly escaping it. Try defining the template as:
template: "<a class='change-image' href='javascript:void(0);' title='Print Treatment Form' onclick='printForm(\"#= Physician #\")'><img alt='Student Info' src='#Url.Content("~/Content/Images/printer-icon.png")' /></a>"
Check it here: http://jsfiddle.net/OnaBai/ZwXa2/
columns.Bound(m => m.Name).Title("Subsys #").ClientTemplate("#= Name #");
This is razor syntax, you can insert some arbitrary string like this 'stringValue'

Resources