can you help me to fix my problem, I made gridview, and I use combobox to filter data in gridview and get gridview performcallback after filter, but gridview not callback after filter. how can I do ? Help me Please?
this is some code :
controller gridview filter :
[HttpPost]
public ActionResult FilterTypePro(String typePro)
{
//Session["typePro"] = typePro;
var model = Model._ProposalObject.ListDataProposal();
if (typePro != null && typePro != string.Empty)
{
model = Model._ProposalObject.ListDataProposal(typePro);
}
return PartialView("_gvPartialViewProposals", model);
}
and this is code to get value filter combobox :
function OnClickFilter(type) {
type = cbTypeProposal.GetValue();
$.ajax({
type: "POST",
cache: false,
async: false,
url: '#Url.Action("FilterTypePro", "App")',
data: { 'typePro': type },
success: function (data) {
/*gvPartialViewProposals.AdjustControl();
try {
gvPartialViewProposals.PerformCallback();
}
catch(er){
}*/
gvPartialViewProposals.Refresh(data);
}
});
}
and this is code to view cshtml :
groupItem.Items.Add(item =>
{
item.Caption = "Type Of Proposal";
item.Width = 400;
item.SetNestedContent(() =>
{
ViewContext.Writer.Write("<table><tr><td>");
Html.DevExpress().ComboBox(cmbSettings =>
{
cmbSettings.Name = "cbTypeProposal";
cmbSettings.Width = 100;
cmbSettings.Properties.DropDownStyle = DropDownStyle.DropDownList;
cmbSettings.ShowModelErrors = true;
cmbSettings.Properties.Items.Add("ATL", "ATL");
cmbSettings.Properties.Items.Add("BTL", "BTL");
cmbSettings.Properties.ClientSideEvents.SelectedIndexChanged = "function(s, e) { OnClickFilter();}";
}).Render();
ViewContext.Writer.Write("</td></tr></table>");
});
}); ;
}).GetHtml();
I hope you can help me.
Modify your javascript function as follows:
function OnClickFilter(type){
type = cbTypeProposal.GetValue();
gvPartialViewProposals.PerformCallback({
'typePro': type
});
}
Modify your grid settings as follows:
settings.Name = "gvPartialViewProposals";
settings.CustomActionRouteValues = new { Controller = "App", Action = "FilerTypePro" };
Related
I am using a vtiger Crm system and I would like to use the pop up notification to display my own messages. I wrote an event handler that triggers after model save, in this handler I would like to call the notification box with my own message.
Here is a working example that is from the 'Products' module handlers, this code was pre-written, it checks if there were duplicate item numbers and shows a message 'LBL_DUPLICATE_item_number' in the pop-up box
class Products_DuplicateItemNumber_Handler
{
/**
* EditViewPreSave handler function.
*
* #param App\EventHandler $eventHandler
*/
public function editViewPreSave(App\EventHandler $eventHandler)
{
$recordModel = $eventHandler->getRecordModel();
$response = ['result' => true];
$fieldModel = $recordModel->getModule()->getFieldByName('item_number');
if ($fieldModel->isViewable() && ($item_number = $recordModel->get('item_number'))) {
$queryGenerator = new \App\QueryGenerator($recordModel->getModuleName());
$queryGenerator->setStateCondition('All');
$queryGenerator->setFields(['id'])->permissions = false;
$queryGenerator->addCondition($fieldModel->getName(), $item_number, 'e');
if ($recordModel->getId()) {
$queryGenerator->addCondition('id', $recordModel->getId(), 'n');
}
if ($queryGenerator->createQuery()->exists()) {
$response = [
'result' => false,
'hoverField' => 'item_number',
'message' => App\Language::translate('LBL_DUPLICATE_item_number', $recordModel->getModuleName())
];
}
}
return $response;
}
}
However, when i try to return $respone in 'editViewPreSave' of another module, nothing happens.
After some digging around i found out that the system uses 'Pnotify' library to show the pop up message, and i belive it's being called in a js file called 'edit.js' in this path 'public_html/layouts/basic/modules/Vtiger/resources'
preSaveValidation: function (form) {
const aDeferred = $.Deferred();
if (form.find('#preSaveValidation').val()) {
document.progressLoader = $.progressIndicator({
message: app.vtranslate('JS_SAVE_LOADER_INFO'),
position: 'html',
blockInfo: {
enabled: true
}
});
let formData = new FormData(form[0]);
formData.append('mode', 'preSaveValidation');
AppConnector.request({
async: false,
url: 'index.php',
type: 'POST',
data: formData,
processData: false,
contentType: false
})
.done((data) => {
document.progressLoader.progressIndicator({ mode: 'hide' });
let response = data.result;
for (let i = 0; i < response.length; i++) {
if (response[i].result !== true) {
app.showNotify({
text: response[i].message ? response[i].message : app.vtranslate('JS_ERROR'),
type: 'error'
});
if (response[i].hoverField != undefined) {
form.find('[name="' + response[i].hoverField + '"]').focus();
}
}
}
aDeferred.resolve(data.result.length <= 0);
})
.fail((textStatus, errorThrown) => {
document.progressLoader.progressIndicator({ mode: 'hide' });
app.showNotify({
text: app.vtranslate('JS_ERROR'),
type: 'error'
});
app.errorLog(textStatus, errorThrown);
aDeferred.resolve(false);
});
} else {
aDeferred.resolve(true);
}
return aDeferred.promise();
},
I believe that 'app.showNotify' is the function called to display the pop-up box, yet i'm not sure how to replicate the code for my own use, i would like to know the best approach to do this
I'm having an issue with Kendo Grid in Angular where the custom drop down I've implemented will not open when tab navigating to that column. The built in text and number editor fields are editable on tab navigation but my custom drop down will not expand. I have to click on it to get the drop down effect.
My goal here is to allow the user to log an an entire row of data without having to take their hands off the keyboard.
My column is defined like so:
gridColumns.push({
field: currentField.FieldName.replace(/ /g, "_"),
title: currentField.FieldName,
editor: $scope.dropDownAttEditor,
template: function (dataItem) {
return $scope.dropDownTemplate(dataItem, currentField.FieldName);
}
});
My gridOptions are defined as follows:
$scope.gridOptions = {
dataSource: new kendo.data.DataSource({
transport: {
read: {
url: appconfig.basePath + '/api/DrillHoleManager/DrillHoleInterval',
type: 'POST',
contentType: 'application/json'
},
update: {
url: appconfig.basePath + '/api/DrillHoleManager/DrillHoleIntervalUpdate',
type: 'POST',
contentType: 'application/json'
},
parameterMap: function (data, operation) {
if (operation === "read") {
data.DrillHoleId = $scope.entity.Id;
data.DrillHoleIntervalTypeId = $stateParams.ddhinttypeid;
// convert the parameters to a json object
return kendo.stringify(data);
}
if (operation === 'update') {
// build DrillHoleIntervalDto object with all ATT/CMT values to send back to server
var drillHoleInterval = { Id: data.Id, Name: data.Name, From: data.From, To: data.To };
drillHoleInterval.Attributes = [];
drillHoleInterval.Comments = [];
var attributeFields = $.grep($scope.currentFields, function (e) { return e.DrillHoleTabFieldType == DrillHoleTabFieldTypeEnum.IntervalAttribute });
$.each(attributeFields, function (idx, attributeField) {
drillHoleInterval.Attributes.push({
Id: attributeField.AttributeDto.Id,
LookupId: data[attributeField.FieldName.replace(/ /g, "_")]
});
});
var commentFields = $.grep($scope.currentFields, function (e) { return e.DrillHoleTabFieldType == DrillHoleTabFieldTypeEnum.IntervalComment });
$.each(commentFields, function (idx, commentField) {
drillHoleInterval.Comments.push({
Id: commentField.CommentDto.Id,
Value: ((data[commentField.FieldName.replace(/ /g, "_")] != "") ? data[commentField.FieldName.replace(/ /g, "_")] : null)
});
});
return kendo.stringify(drillHoleInterval);
}
// ALWAYS return options
return options;
}
},
schema: { model: { id : "Id" }},
serverPaging: false,
serverSorting: false,
serverFiltering: false
//,autoSync: true
}),
columns: gridColumns,
dataBound: onDataBound,
autoBind: false,
navigatable: true,
scrollable: false,
editable: true,
selectable: true,
edit: function (e) {
var grid = $("#ddhintgrid").data("kendoGrid");
//grid.clearSelection();
grid.select().removeClass('k-state-selected');
// select the row currently being edited
$('[data-uid=' + e.model.uid + ']').addClass('k-state-selected');
e.container[0].focus();
}
};
Here is a custom event to handle the 'Tab' keypress. The point of this is I want a new record automatically added to the grid if the user presses 'Tab' at the end of the last line:
$("#ddhintgrid").keydown(function (e) {
if (e.key == "Tab") {
var grid = $("#ddhintgrid").data("kendoGrid");
var data = grid.dataSource.data();
var selectedItem = grid.dataItem(grid.select());
var selectedIndex = null
if (selectedItem != null) {
selectedIndex = grid.select()[0].sectionRowIndex;
if (selectedIndex == data.length - 1) { // if the bottom record is selected
// We need to manually add a new record here so that the new row will automatically gain focus.
// Using $scope.addRecord() here will add the new row but cause the grid to lose focus.
var newRecord = { From: grid.dataSource.data()[selectedIndex].To };
var currentCmtFields = $.grep($scope.currentFields, function (e) { return e.DrillHoleTabFieldType == DrillHoleTabFieldTypeEnum.IntervalComment; });
$.each(currentCmtFields, function (idx, currentCmtField) {
newRecord[currentCmtField.FieldName.replace(/ /g, "_")] = null;
});
grid.dataSource.insert(data.length, newRecord);
// edit the new row
grid.editRow($("#ddhintgrid tr:eq(" + (data.length) + ")"));
}
}
}
});
Here is my template for the drop down column:
$scope.dropDownTemplate = function (dataItem, fieldName) {
var currentLookups = $.grep($scope.currentFields, function (e) { return e.FieldName == fieldName; })[0].AttributeDto.Lookups;
var selectedLookup = $.grep(currentLookups, function (e) { return e.Id == dataItem[fieldName.replace(/ /g, "_")]; })[0];
// With the custom dropdown editor when going from null to a value the entire lookup object (id, name) is placed in the
// dataItem[field_name] instead of just the id. We need to replace this object with just the id value and return the name of
// the lookup to the template.
if (typeof selectedLookup == 'undefined' && dataItem[fieldName.replace(/ /g, "_")] != null) {
selectedLookup = angular.copy(dataItem[fieldName.replace(/ /g, "_")]);
dataItem[fieldName.replace(/ /g, "_")] = selectedLookup.Id;
}
if (selectedLookup != null && selectedLookup != '') {
return selectedLookup.Name;
}
else {
return '';
}
};
And finally here is the custom editor for the drop down column:
$scope.dropDownAttEditor = function (container, options) {
var editor = $('<input k-data-text-field="\'Name\'" k-data-value-field="\'Id\'" k-data-source="ddlDataSource" data-bind="value:' + options.field + '"/>')
.appendTo(container).kendoDropDownList({
dataSource: $.grep($scope.currentFields, function (e) { return e.FieldName == options.field.replace(/_/g, ' '); })[0].AttributeDto.Lookups,
dataTextField: "Name",
dataValueField: "Id"
});
};
I know this is a lot to take in but if you have any questions just let me know.
My ultimate goal is that I want the user to be able to navigate the grid using the 'Tab' key and edit every field without having to use the mouse.
I have tried to reload the data populated by an ajax call but I cant get it to work, it shows the old data even after using the reload method. The thing is that if I change some variables to populate a different data and try to call the following code without refreshing the page it does not reload the updated data =/ Here is my code:
function populateDataGrid() {
$.ajaxSetup({async: false});
var gridinfo="";
$.post("lib/function.php",{activity: activity, shift: shift, date: date},
function (output){
gridinfo = JSON.parse(output);
});
$.ajaxSetup({async: true});
// INITIALIZING THE DATAGRID
var dataSource = new StaticDataSource({
columns: [
{
property: 'id',
label: '#',
sortable: true
},
{
property: 'date',
label: 'date',
sortable: true
},
....
],
formatter: function (items) {
var c=1;
$.each(items, function (index, item) {
item.select = '<input type="button" id="select'+c+'" class="select btn" value="select" onclick="">';
c=c+1;
});
},
data: gridinfo,
delay:300
});
$('#grid').datagrid({
dataSource: dataSource
});
$('#grid').datagrid('reload');
$('#modal-fast-appointment-results').modal({show:true});
}
I found a solution... I had to create a new DataSource (lets call it "AjaxDataSource") and add the ajax request functionality within the data constructor:
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(['underscore'], factory);
} else {
root.AjaxDataSource = factory();
}
}(this, function () {
var AjaxDataSource = function (options) {
this._formatter = options.formatter;
this._columns = options.columns;
this._delay = options.delay || 0;
this._data = options.data;
};
AjaxDataSource.prototype = {
columns: function () {
return this._columns;
},
data: function (options, callback) {
var self = this;
setTimeout(function () {
var data;
$.ajax({
url: 'getdata.php',
type: 'POST',
data: 'param1:param1,param2,param2,...,paramN:paramN', // this is optional in case you have to send some params to getdata.php
dataType: 'json',
async: false,
success: function(result) {
data = result;
},
error: function(data){
//in case we want to debug and catch any possible error
// console.log(data);
}
});
// SEARCHING
if (options.search) {
data = _.filter(data, function (item) {
var match = false;
_.each(item, function (prop) {
if (_.isString(prop) || _.isFinite(prop)) {
if (prop.toString().toLowerCase().indexOf(options.search.toLowerCase()) !== -1) match = true;
}
});
return match;
});
}
var count = data.length;
// SORTING
if (options.sortProperty) {
data = _.sortBy(data, options.sortProperty);
if (options.sortDirection === 'desc') data.reverse();
}
// PAGING
var startIndex = options.pageIndex * options.pageSize;
var endIndex = startIndex + options.pageSize;
var end = (endIndex > count) ? count : endIndex;
var pages = Math.ceil(count / options.pageSize);
var page = options.pageIndex + 1;
var start = startIndex + 1;
data = data.slice(startIndex, endIndex);
if (self._formatter) self._formatter(data);
callback({ data: data, start: start, end: end, count: count, pages: pages, page: page });
}, this._delay)
}
};
return AjaxDataSource;
}));
After defining the new DataSource, we just need to create it and call the datagrid as usual:
function populateDataGrid(){
// INITIALIZING THE DATAGRID
var dataSource = new AjaxDataSource({
columns: [
{
property: 'id',
label: '#',
sortable: true
},
{
property: 'date',
label: 'date',
sortable: true
},
....
],
formatter: function (items) { // in case we want to add customized items, for example a button
var c=1;
$.each(items, function (index, item) {
item.select = '<input type="button" id="select'+c+'" class="select btn" value="select" onclick="">';
c=c+1;
});
},
delay:300
});
$('#grid').datagrid({
dataSource: dataSource
});
$('#grid').datagrid('reload');
$('#modal-results').modal({show:true});
}
So now we have our datagrid with data populated via ajax request with the ability to reload the data without refreshing the page.
Hope it helps someone!
I have a jquery context menu on my landing page where I have hardcode menu items. Now I want to get the menu items from server. Basically the idea is to show file names in a specified directory in the context menu list and open that file when user clicks it...
This is so far I have reached..
***UPDATE***
C# code
[HttpPost]
public JsonResult GetHelpFiles()
{
List<Manuals> manuals = null;
var filesPath = Server.MapPath(#"\HelpManuals");
var standardPath = new DirectoryInfo(filesPath);
if (standardPath.GetFiles().Any())
{
manuals = standardPath.GetFiles().Select(x => new Manuals
{
Name = GetFileNamewithoutExtension(x.Name),
Path = x.Name
}).ToList();
}
return Json(manuals, JsonRequestBehavior.AllowGet);
}
private string GetFileNamewithoutExtension(string filename)
{
var extension = Path.GetExtension(filename);
return filename.Substring(0, filename.Length - extension.Length);
}
JavaScript Code
$.post("/Home/GetHelpFiles", function (data) {
$.contextMenu({
selector: '#helpIcon',
trigger: 'hover',
delay: 300,
build: function($trigger, e) {
var options = {
callback: function(key) {
window.open("/HelpManuals/" + key);
},
items: {}
};
$.each(data, function (item, index) {
console.log("display name:" + index.Name);
console.log("File Path:" + index.Path);
options.items[item.Value] = {
name: index.Name,
key: index.Path
}
});
}
});
});
Thanks to Matt. Now, the build function gets fire on hover.. but im getting illegal invocation... and when iterating through json result, index.Name and this.Name gives correct result. But item.Name doesn't give anything..
to add items to the context menu dynamically you need to make a couple changes
$.contextMenu({
selector: '#helpIcon',
trigger: 'hover',
delay: 300,
build: function($trigger, e){
var options = {
callback: function (key) {
var manual;
if (key == "adminComp") {
manual = "AdminCompanion.pdf";
} else {
manual = "TeacherCompanion.pdf";
}
window.open("/HelpManuals/" + manual);
},
items: {}
}
//how to populate from model
#foreach(var temp in Model.FileList){
<text>
options.items[temp.Value] = {
name: temp.Name,
icon: 'open'
}
</text>
}
//should be able to do an ajax call here but I believe this will be called
//every time the context is triggered which may cause performance issues
$.ajax({
url: '#Url.Action("Action", "Controller")',
type: 'get',
cache: false,
async: true,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (_result) {
if (_result.Success) {
$.each(_result, function(item, index){
options.items[item.Value] = {
name: item.Name,
icon: 'open'
}
});
}
});
return options;
}
});
so you use build and inside of that define options and put your callback in there. The items defined in there is empty and is populated in the build dynamically. We build our list off of what is passed through the model but I believe you can put the ajax call in the build like I have shown above. Hopefully this will get you on the right track at least.
I solved this problem the following way.
On a user-triggered right-click I return false in the build-function. This will prevent the context-menu from opening. Instead of opeing the context-menu I start an ajax-call to the server to get the contextMenu-entries.
When the ajax-call finishes successfully I create the items and save the items on the $trigger in a data-property.
After saving the menuItems in the data-property I open the context-menu manually.
When the build-function is executed again, I get the items from the data-property.
$.contextMenu({
build: function ($trigger, e)
{
// check if the menu-items have been saved in the previous call
if ($trigger.data("contextMenuItems") != null)
{
// get options from $trigger
var options = $trigger.data("contextMenuItems");
// clear $trigger.data("contextMenuItems"),
// so that menuitems are gotten next time user does a rightclick
// from the server again.
$trigger.data("contextMenuItems", null);
return options;
}
else
{
var options = {
callback: function (key)
{
alert(key);
},
items: {}
};
$.ajax({
url: "GetMenuItemsFromServer",
success: function (response, status, xhr)
{
// for each menu-item returned from the server
for (var i = 0; i < response.length; i++)
{
var ri = response[i];
// save the menu-item from the server in the options.items object
options.items[ri.id] = ri;
}
// save the options on the table-row;
$trigger.data("contextMenuItems", options);
// open the context-menu (reopen)
$trigger.contextMenu();
},
error: function (response, status, xhr)
{
if (xhr instanceof Error)
{
alert(xhr);
}
else
{
alert($($.parseHTML(response.responseText)).find("h2").text());
}
}
});
// This return false here is important
return false;
}
});
I have finally found a better solution after reading jquery context menu documentation, thoroughly..
C# CODE
public JsonResult GetHelpFiles()
{
List<Manuals> manuals = null;
var filesPath = Server.MapPath(#"\HelpManuals");
var standardPath = new DirectoryInfo(filesPath);
if (standardPath.GetFiles().Any())
{
manuals = standardPath.GetFiles().Select(x => new Manuals
{
Name = GetFileNamewithoutExtension(x.Name),
Path = x.Name
}).ToList();
}
return Json(manuals, JsonRequestBehavior.AllowGet);
}
HTML 5
<div id="dynamicMenu">
<menu id="html5menu" type="context" style="display: none"></menu>
</div>
JavaScript Code
$.post("/Home/GetHelpFiles", function (data) {
$.each(data, function (index, item) {
var e = '<command label="' + item.Name + '" id ="' + item.Path + '"></command>';
$("#html5menu").append(e);
});
$.contextMenu({
selector: '#helpIcon',
trigger: 'hover',
delay: 300,
items: $.contextMenu.fromMenu($('#html5menu'))
});
});
$("#dynamicMenu").on("click", "menu command", function () {
var link = $(this).attr('id');
window.open("/HelpManuals/" + link);
});
Here's my solution using deferred, important to know that this feature is supported for sub-menus only
$(function () {
$.contextMenu({
selector: '.SomeClass',
build: function ($trigger, e) {
var options = {
callback: function (key, options) {
// some call back
},
items: JSON.parse($trigger.attr('data-storage')) //this is initial static menu from HTML attribute you can use any static menu here
};
options.items['Reservations'] = {
name: $trigger.attr('data-reservations'),
icon: "checkmark",
items: loadItems($trigger) // this is AJAX loaded submenu
};
return options;
}
});
});
// Now this function loads submenu items in my case server responds with 'Reservations' object
var loadItems = function ($trigger) {
var dfd = jQuery.Deferred();
$.ajax({
type: "post",
url: "/ajax.php",
cache: false,
data: {
// request parameters are not importaint here use whatever you need to get data from your server
},
success: function (data) {
dfd.resolve(data.Reservations);
}
});
return dfd.promise();
};
I followed that tutorial about exporting Kendo Grid Data : http://www.kendoui.com/blogs/teamblog/posts/13-03-12/exporting_the_kendo_ui_grid_data_to_excel.aspx
Now I´m trying to export all data (not only the showed page) ... How can I do that?
I tried change the pagezise before get the data:
grid.dataSource.pageSize(grid.dataSource.total());
But with that my actual grid refresh with new pageSize. Is that a way to query kendo datasource without refresh the grid?
Thanks
A better solution is to generate an Excel file from the real data, not from the dataSource.
1]
In the html page, add
$('#export').click(function () {
var title = "EmployeeData";
var id = guid();
var filter = $("#grid").data("kendoGrid").dataSource._filter;
var data = {
filter: filter,
title: title,
guid: id
};
$.ajax({
url: '/Employee/Export',
type: "POST",
dataType: 'json',
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
success: function (result) {
window.location = kendo.format("{0}?title={1}&guid={2}", '/Employee/GetGeneratedExcel', title, id);
}
});
});
2]
Add a method "Export" to the controller:
[HttpPost]
public JsonResult Export(KendoGridFilter filter, string guid)
{
var gridRequest = new KendoGridRequest();
if (filter != null)
{
gridRequest.FilterObjectWrapper = filter.Filters != null ? filter.ToFilterObjectWrapper() : null;
gridRequest.Logic = filter.Logic;
}
var query = GetQueryable().AsNoTracking();
var results = query.FilterBy<Employee, EmployeeVM>(gridRequest);
using (var stream = new MemoryStream())
{
using (var excel = new ExcelPackage(stream))
{
excel.Workbook.Worksheets.Add("Employees");
var ws = excel.Workbook.Worksheets[1];
ws.Cells.LoadFromCollection(results);
ws.Cells.AutoFitColumns();
excel.Save();
Session[guid] = stream.ToArray();
return Json(new { success = true });
}
}
}
3]
Also add the method "GetGeneratedExcel" to the controller:
[HttpGet]
public FileResult GetGeneratedExcel(string title, string guid)
{
// Is there a spreadsheet stored in session?
if (Session[guid] == null)
{
throw new Exception(string.Format("{0} not found", title));
}
// Get the spreadsheet from session.
var file = Session[guid] as byte[];
string filename = string.Format("{0}.xlsx", title);
// Remove the spreadsheet from session.
Session.Remove(title);
// Return the spreadsheet.
Response.Buffer = true;
Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", filename));
return File(file, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", filename);
}
Also see this project on github.
See this live example project where you can export the Employees to Excel. (Although this returns filtered data, but you can modify the code to ignore the kendo grid filter and always return all data.
Really old question but:
To export all the pages use excel.allPages:
$("#grid").kendoGrid({
toolbar: ["excel"],
excel: {
allPages: true
},
// ....
});
See Example
Grid toolbar
..
.ToolBar(toolbar =>
{
toolbar.Template(
#<text>
#Html.Kendo().Button().Name("grid-export").HtmlAttributes(new { type = "button", data_url = #Url.Action("Export") }).Content("Export").Events(ev => ev.Click("exportGrid"))
</text>);
})
..
Endpoint export function
public FileResult Export([DataSourceRequest]DataSourceRequest request)
{
DemoEntities db = new DemoEntities();
byte[] bytes = WriteExcel(db.Table.ToDataSourceResult(request).Data, new string[] { "Id", "Name" });
return File(bytes,
"application/vnd.ms-excel",
"GridExcelExport.xls");
}
a javascript function to generate grid remote export url with all specified parameters
function exportGrid() {
var toolbar = $(this.element);
var gridSelector = toolbar.closest(".k-grid");
var grid = $(gridSelector).data("kendoGrid");
var url = toolbar.data("url");
var requestObject = (new kendo.data.transports["aspnetmvc-server"]({ prefix: "" }))
.options.parameterMap({
page: grid.dataSource.page(),
sort: grid.dataSource.sort(),
filter: grid.dataSource.filter()
});
url = url + "?" + $.param({
"page": requestObject.page || '~',
"sort": requestObject.sort || '~',
"pageSize": grid.dataSource.pageSize(),
"filter": requestObject.filter || '~',
});
window.open(url, '_blank');
}
For detailed solution see my sample project on Github
where u can export grid server side with current configuration (sorting, filtering, paging) using helper function