Kendo UI Grid custom sorting - asp.net-mvc

I have a grid in my application where the user wants the following functionality.
Scenerio
There are 4 columns in the grid, let's call them A, B, C and D.
Multiple columns are sortable and can be reordered.
The default sort is column A, B, C, D
If the user drags column C to be the first column, then the sort should be C, A, B, D.
I know there's a columnOrder event on the grid. Is this functionality possible? Is there an example anywhere or could someone give me direction on how to accomplish this functionality?
Thanks
Jim

In the event handler you can get the new column order from: this.columns. Then you should compose the sorting criteria and apply it.
Something like:
columnReorder: function() {
var sort = [];
$.each(this.columns, function(idx, elem) {
// In my case order by those columns that start with "Ship"
if (elem.field.lastIndexOf("Ship", 0) === 0) {
sort.push({field: elem.field, dir: "asc"});
}
});
this.dataSource.sort(sort);
},
Following a runnable example.
$(document).ready(function() {
$("#grid").kendoGrid({
dataSource: {
type: "odata",
transport: {
read: "http://demos.telerik.com/kendo-ui/service/Northwind.svc/Orders"
},
schema: {
model: {
fields: {
OrderID: { type: "number" },
ShipCountry: { type: "string" },
ShipCity: { type: "string" },
ShipName: { type: "string" },
OrderDate: { type: "date" },
ShippedDate: {type: "date" }
}
}
},
pageSize: 15
},
height: 550,
sortable: true,
reorderable: true,
resizable: true,
pageable: true,
columnReorder: function() {
var sort = [];
$.each(this.columns, function(idx, elem) {
if (elem.field.lastIndexOf("Ship", 0) === 0) {
sort.push({field: elem.field, dir: "asc"});
}
});
this.dataSource.sort(sort);
},
columns: [
{
field: "OrderID",
title: "ID",
width: 80
},
{
field: "ShipCity",
title: "Ship City"
},
{
field: "ShipName",
title: "Ship Name"
},
{
field: "ShippedDate",
title: "Shipped Date",
format: "{0:MM/dd/yyyy}",
width: 200
}
]
});
});
<link rel="stylesheet" href="http://cdn.kendostatic.com/2015.2.624/styles/kendo.common-office365.min.css" />
<link rel="stylesheet" href="http://cdn.kendostatic.com/2015.2.624/styles/kendo.office365.min.css" />
<script src="http://cdn.kendostatic.com/2015.2.624/js/jquery.min.js"></script>
<script src="http://cdn.kendostatic.com/2015.2.624/js/kendo.all.min.js"></script>
<div id="grid"></div>

Related

How to insert a dropdownlist in the header of a kendo ui grid to adjust its column value

I am trying to insert a dropdownlist on the title of a kendo ui grid. Essentially I am following this sample: http://dojo.telerik.com/#rkonstantinov/afOxa
The following is my code.
<div id="grid"></div>
<script type="text/x-kendo-template" id="myFileCount">
<input type="search" id="fileCountValue" style="width: 150px"/>
</script>
$("#grid").kendoGrid({
dataSource: dataSource,
columns: [
{
hidden: true,
field: "ID",
},
{
field: "FileCount",
title: "FileCount",
headerTemplate: kendo.template($("#myFileCount").html()),
width: 50,
sortable: false
},
],
editable: true
});
var gridA = $("#grid").data("kendoGrid");
gridA.find("#fileCountValue").kendoDropDownList({ //this line throws error
autoBind: false,
optionLabel: "All",
dataSource: [
{ Name: "1", Id: 1 },
{ Name: "2", Id: 2 }
],
dataTextField: "Name",
dataValueField: "Id",
change:function() {
var val = this.value();
for (var i = 0; i < dataSource.data().length; i++) {
dataSource.data()[i].Originals = val;
}
dataSource.data()[i].Originals = val;
grid.setDataSource(dataSource);
}
});
However, I am getting this error: 0x800a01b6 - JavaScript runtime error: Object doesn't support property or method 'find'. I have also indicated the line which throws this error in my code.
Thanks

How do I build a grid of PortfolioItem/Features with associated User Stories that have no children?

I want to create a custom grid on My Dashboard of User Stories under a portfolio item without child stories.
A custom grid on My Dashboard with Object: PortfolioIetm Feature and query UserStories.DirectChildrenCount = 0
it will produce this error:
Could not parse: Attribute "UserStories" on type PortfolioItems is not allowed in query expressions.
Here is a custom App SDK 2 app that builds a grid of Features with user stories where DirectChildrenCount = 0. It accesses the collection of stories on every feature
var stories = feature.getCollection('UserStories');
but populates the grid only with those stories that have no children. Here is the full App.html code that can be pasted into a custom tab:
<!DOCTYPE html>
<html>
<head>
<title>GridExample</title>
<script type="text/javascript" src="/apps/2.0rc1/sdk.js"></script>
<script type="text/javascript">
Rally.onReady(function () {
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function() {
Ext.create('Rally.data.WsapiDataStore', {
model: 'PortfolioItem/Feature',
fetch: ['FormattedID','Name','UserStories'],
pageSize: 100,
autoLoad: true,
listeners: {
load: this._onDataLoaded,
scope: this
}
});
},
_createGrid: function(features) {
this.add({
xtype: 'rallygrid',
store: Ext.create('Rally.data.custom.Store', {
data: features,
pageSize: 100
}),
columnCfgs: [
{
text: 'Formatted ID', dataIndex: 'FormattedID', xtype: 'templatecolumn',
tpl: Ext.create('Rally.ui.renderer.template.FormattedIDTemplate')
},
{
text: 'Name', dataIndex: 'Name'
},
{
text: 'Story Count', dataIndex: 'StoryCount'
},
{
text: 'User Stories', dataIndex: 'UserStories',
renderer: function(value) {
var html = [];
Ext.Array.each(value, function(userstory){
html.push('' + userstory.FormattedID + '')
});
return html.join(', ');
}
}
]
});
},
_onDataLoaded: function(store, data){
var features = [];
var pendingstories = data.length;
//debugger;
Ext.Array.each(data, function(feature) {
var f = {
FormattedID: feature.get('FormattedID'),
Name: feature.get('Name'),
_ref: feature.get("_ref"),
StoryCount: feature.get('UserStories').Count,
UserStories: []
};
var stories = feature.getCollection('UserStories');
stories.load({
fetch: ['FormattedID'],
callback: function(records, operation, success){
Ext.Array.each(records, function(story){
var number = story.get('DirectChildrenCount');
if (number == 0) {
f.UserStories.push({_ref: story.get('_ref'),
FormattedID: story.get('FormattedID')
});}
}, this);
--pendingstories;
if (pendingstories === 0) {
this._createGrid(features);
}
},
scope: this
});
features.push(f);
}, this);
}
});
Rally.launchApp('CustomApp', {
name:"GridExample"
//parentRepos:""
});
});
</script>
<style type="text/css">
.app {
/* Add app styles here */
}
</style>
</head>
<body></body>
</html>

jqgrid with custom column

I am using Jqgrid in my application. I wanted to create a column with 2 buttons. I want to have in column since the buttons may differ based on the data of the row. I googled it and I am able to found only creating a button using custom formatter option, but it appears only on double clicking a row or on edit of a row, but I want it to be displayed on column itself. Any help or link containing information will be appreciated. Below is my grid code.
Need to create an another column with buttons.
Edit:
var grid = $(gridId);
grid.jqGrid({
data: gridData,
datatype: "local",
gridview: true,
colModel: [
{
label: 'Employee Name', name: 'employeeName', width: 195, editable:true,
sortable:true, editrules:{required:true}
},
{
label: 'Address', name: 'address', width: 170, editable:true,
sortable:true,
editrules:{required:true}
},
{
label: 'Department', name: 'department', width: 120, editable:true,
sortable:true,
edittype:'custom',
editoptions: {
'custom_element' : populateReturnTypeAutocomplete,
'custom_value' : autocomplete_value
},
editrules:{required:true}
},
});
Okay add this to your colModal
{label: 'My Custom Column', name: 'custom', index:'custom' width: 120}
Now in gridComplete or loadComplete add this code
var grid = $("#grid"),
iCol = getColumnIndexByName(grid,'custom'); // 'custom' - name of the actions column
grid.children("tbody")
.children("tr.jqgrow")
.children("td:nth-child("+(iCol+1)+")")
.each(function() {
$("<div>",
{
title: "button1",
mouseover: function() {
$(this).addClass('ui-state-hover');
},
mouseout: function() {
$(this).removeClass('ui-state-hover');
},
click:
handle your click function here
}
).css({"margin-left": "5px", float:"left"})
.addClass("ui-pg-div ui-inline-save")
.attr('id',"customId")
.append('<span class="ui-button-icon-primary ui-icon ui-icon-disk"></span>')
.appendTo($(this).children("div"));
$("<div>",
{
title: "custombutton 2",
mouseover: function() {
$(this).addClass('ui-state-hover');
},
mouseout: function() {
$(this).removeClass('ui-state-hover');
},
click:
handle click here
}
).css({"margin-left": "5px", float:"left"})
.addClass("ui-pg-div ui-inline-custom")
.attr('id',"customButton2")
.append('<span class="ui-button-icon-primary ui-icon ui-icon-circle-check"></span>')
.appendTo($(this).children("div"));
Now these icons I'm adding here will be available with jquery ui.css and you will have to add one more function to your script which will get 'custom' column index for u in line first of above code.
var getColumnIndexByName = function(grid,columnName) {
var cm = grid.jqGrid('getGridParam','colModel'), i=0,l=cm.length;
for (; i<l; i+=1) {
if (cm[i].name===columnName) {
return i; // return the index
}
}
return -1;
};
I hope this helps.

asp.net mvc jqgrid submit grid using a button outside of the grid

I'm new to jqgrid and MVC. My Jqgrid is in multi select mode, and I want to submit all selected items on the grid to the controller by clicking on a button (tbrSave) outside of the grid.
#using (Html.BeginForm("Save", "Home"))
{
<button type="submit" id="tbrSave" class="toolbar">
<span title="Config" class="icon-32-save"></span>Save</button>
<script src="#Url.Content("~/Scripts/grid.locale-en.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.jqGrid.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery-ui-1.8.11.custom.min.js")" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
var lastSelectedRow;
$('#jqGridCategoryCreate').jqGrid({
//url from wich data should be requested
url: 'CategoriesList',
//type of data
datatype: 'json',
editurl: '#Url.Action("UpdateCategory")',
//url access method type
mtype: 'POST',
//columns names
colNames: ['CategoryId', 'Category Name', 'Display Order', 'Is Featured Product'], //columns model
colModel: [
{ name: 'Id', index: 'Id', align: 'left', editable: false },
{ name: 'Name', index: 'Name', align: 'left', editable: false },
{ name: 'DisplayOrder', index: 'DisplayOrder', align: 'left', editable: true, edittype: 'text', editoptions: { maxlength: 10 }, editrules: { required: true} },
{ name: 'IsFeaturedProduct', index: 'IsFeaturedProduct', align: 'left', editable: true, edittype: 'text', edittype: 'checkbox', editoptions: { maxlength: 10, value: '1:Yes;0:No' }, formatter: 'checkbox', editrules: { required: true}}],
//pager for grid
pager: $('#jqPagerCategoryCreate'),
//number of rows per page
rowNum: 10,
//initial sorting column
sortname: 'Id',
//initial sorting direction
sortorder: 'asc',
//we want to display total records count
viewrecords: true,
multiselect: true,
//grid width
width: 'auto',
//grid height
height: 'auto',
ondblClickRow: function (id) {
if (id && id != lastSelectedRow) {
//save changes in row
jQuery('#jqGridCategoryCreate').saveRow(lastSelectedRow);
$.lastSelectedRow = id;
//trigger inline edit for row
$('#jqGridCategoryCreate').editRow(lastSelectedRow, true);
}
}
});
$('#jqGridCategoryCreate').jqGrid('navGrid', '#jqPagerCategoryCreate',
{ add: false, del: true, edit: false, search: false },
{ width: 'auto', url: '/Category/Edit' },
{ width: 'auto', url: 'SaveCustomLanguageData' },
{ width: 'auto', url: '/Category/Delete' });
function getSelectedRows() {
//make sure all items must be in view mode before submitting.
jQuery('#jqGridCategoryCreate').saveRow(lastSelectedRow);
var rows = $("#jqGridCategoryCreate").jqGrid('getGridParam', 'selarrrow');
var categories = [];
$.each(rows, function (index, rowId) {
var gridRow = $("#jqGridCategoryCreate").getRowData(rowId);
var category = { "Id": rowId,
"DisplayOrder": gridRow['DisplayOrder']
};
categories.push(category);
});
}
});
</script>
}
How can I attach getSelectedRows to the grid in order to post it to Controller ("Save").
Thanks a mil.
Nam Vo.
This would involve following steps
1) Create a anchor link on your razor view
<a id="somelink" href="">Select Multiple Accounts</a>
2) Create a click event handler for anchor link created above
$('#somelink').click(function () {
var multiplerowdata = jQuery("#grid").getGridParam('selarrrow');
$.ajax({ type: 'POST',
url: '#Url.Action("YourController", "YourActionMethod")',
data: JSON.stringify(multiplerowdata),
traditional: true,
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function () { alert("row submited"); }
});})
3) At times you may get javascript error of JSON is not defined, this can be solved by inserting meta tags in shared\_layout.cshtml page as shown below
<meta http-equiv="X-UA-Compatible" content="IE=8" />
4) YourActionMethod inside YourController should like be somewhat like this
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult YourActionMethod(List<string> datarow)
{
//return "sucessfully validated";
return null;
}

How to enable excel export button for jqGrid

Hello
I want to show "export to excel" button in the pager of jqgrid. I tried many ways, read many articles/posts, but I don't see this button. Documentation does not have anything useful too. Which actions should I do to see this button
Ps. I use ASP.NET MVC
PSS. my code is
<link href="../../Scripts/jquery.UI/css/redmond/jquery-ui-1.8.1.custom.css" rel="Stylesheet"
type="text/css" />
<link href="../../Scripts/jquery.jqGrid/css/ui.jqgrid.css" rel="Stylesheet" type="text/css" />
<script type="text/javascript" src="../../Scripts/jquery.jqGrid/js/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="../../Scripts/jquery.jqGrid/js/i18n/grid.locale-ru.js"></script>
<script type="text/javascript" src="../../Scripts/jquery.jqGrid/js/jquery.jqGrid.min.js"></script>
<table id="EmployeeTable">
</table>
<div id="EmployeeTablePager">
</div>
<script type="text/javascript">
jQuery(document).ready(function () {
jQuery('#EmployeeTable').jqGrid({
url: '/Employee/EmployeeData',
datatype: "json",
mtype: 'POST',
jsonReader: {
page: "page",
total: "total",
records: "records",
root: "rows",
repeatitems: false,
id: ""
},
colNames: ['Id', 'Имя', 'Фамилия', 'Email', 'Date'],
colModel: [
{ name: 'Id', width: 20 },
{ name: 'FirstName', width: 105 },
{ name: 'LastName', width: 100 },
{ name: 'Email', width: 150 },
{ name: 'Date', width: 150, formatter: ndateFormatter }
],
pager: '#EmployeeTablePager',
excel: true,
viewrecords: true
}).jqGrid('navButtonAdd',
'#EmployeeTablePager',
{ caption: " Export to Excel ",
buttonicon: "ui-icon-bookmark",
onClickButton: genCSV, position: "last"
});
});
function genCSV() {
alert('a');
}
function ndateFormatter(cellval, opts, rwdat, _act) {
var time = cellval.replace(/\/Date\(([0-9]*)\)\//, '$1');
var date = new Date();
date.setTime(time);
return date.toDateString();
}
</script>
but I don't see the excel import button.
http://ru.magicscreenshot.com/jpg/t97BDzCIO0Q.html
why?
Assuming markup of
<table id="jqgrid"></table>
<div id="pager"></div>
Something along the lines of
$('#grid')
.jqGrid({
datatype: "clientSide",
height: 190,
colNames: headers,
colModel: model,
multiselect: true,
pager: '#pager',
pgbuttons: false,
pginput: false,
caption: "Random Data",
deselectAfterSort: false,
width: 930
})
.jqGrid('navButtonAdd',
'#pager',
{caption:" Export to Excel ",
buttonicon:"ui-icon-bookmark",
onClickButton: genCSV, position:"last"});
genCSV will be a JavaScript function that will make the call to the controller action to generate a CSV file.
Here's an example, in combination with jQuery flot. Create some data, select some grid rows and then click the generate graph button in the bottom left of the grid to plot the points. Note that this will not work in Internet Explorer less than 8 as it requires support for the HTML 5 canvas element (and I haven't bothered to include excanvas).
EDIT:
Your markup is not working because you need to initialize a navGrid before being able to set a custom button (see note on page). You can do this like so
jQuery(document).ready(function () {
jQuery('#EmployeeTable').jqGrid({
url: '/Employee/EmployeeData',
datatype: "json",
mtype: 'POST',
jsonReader: {
page: "page",
total: "total",
records: "records",
root: "rows",
repeatitems: false,
id: ""
},
colNames: ['Id', 'Имя', 'Фамилия', 'Email', 'Date'],
colModel: [
{ name: 'Id', width: 20 },
{ name: 'FirstName', width: 105 },
{ name: 'LastName', width: 100 },
{ name: 'Email', width: 150 },
{ name: 'Date', width: 150, formatter: ndateFormatter }
],
pager: '#EmployeeTablePager',
excel: true,
viewrecords: true
})
/* Need to initialize navGird before being able to set any custom buttons */
.jqGrid('navGrid', '#EmployeeTablePager', {
add: false,
edit: false,
del: false,
search: false,
refresh: false
}).jqGrid('navButtonAdd',
'#EmployeeTablePager',
{ caption: " Export to Excel ",
buttonicon: "ui-icon-bookmark",
onClickButton: genCSV, position: "last"
});
});
function genCSV() {
alert('a');
}
function ndateFormatter(cellval, opts, rwdat, _act) {
var time = cellval.replace(/\/Date\(([0-9]*)\)\//, '$1');
var date = new Date();
date.setTime(time);
return date.toDateString();
}
What I did was to create a csv file on the server and display a download link next to the grid in my view.
It's not as slick as what you have in mind but it is quick and easy to implement.
Extension method to create a csv file from a list (from another post on SO):
public static string AsCsv<T>(this IEnumerable<T> items)
where T : class
{
var csvBuilder = new StringBuilder();
var properties = typeof(T).GetProperties();
foreach (T item in items)
{
//string line = properties.Select(p => p.GetValue(item, null).ToCsvValue()).ToArray().Join(",");
string line= string.Join(", ", properties.Select(p => p.GetValue(item, null).ToCsvValue()).ToArray());
csvBuilder.AppendLine(line);
}
return csvBuilder.ToString();
}
private static string ToCsvValue<T>(this T item)
{
if (item is string)
{
return string.Format("\"{0}\"", item.ToString().Replace("\"", "\\\""));
}
double dummy;
if (double.TryParse(item.ToString(), out dummy))
{
return string.Format("{0}", item.ToString());
}
return string.Format("\"{0}\"", item.ToString());
}
Controller:
model.AListOfData.ToArray().AsCsv();
using (StreamWriter sw = System.IO.File.CreateText(errorFilePath))
{
sw.Write(values);
}
model.ErrorFullFileName = errorFilePath;
In the view:
<%=Html.ImageLink("", "AssetUpload", "DownloadErrors", "/?filename=" + Model.ErrorFullFileName, "/Content/Icons/excel.png", "Download errors and warnings", "imagelink")%>
I used this and it works pretty well
jQuery("#table_resultats").jqGrid('navGrid', "#yourpager").jqGrid( //#pager
'navButtonAdd', "#yourpager", {
caption : "Excel export",
buttonicon : "ui-icon-arrowthickstop-1-s",
onClickButton : null,
position : "first",
title : Excel export,
cursor : "pointer"
});

Resources