In Kendo UI Grid, After grouping grouped column sorting is not working, remaining column sorting is working fine.
Can anyone give me idea on how to sort grouped column from client side.
Thank you!!
When you group your data in kendo grid it automatically sort groups asc.
You can read about this behavior in docs
But what you need is change group sorting on column header click.
on dataBound event try to look at grid dataSource.sort() collection and if need change group sorting direction.
Something like this:
//Get the grid object
var grid = $("#grid").data("kendoGrid");
// Get the datasource bound to the grid
var ds = grid.dataSource;
// Get current sorting
var sort = ds.sort();
// Display sorting fields and direction
if (sort) {
for (var i = 0; i < sort.length; i++) {
if(sort[i].field == " myField"){
grid.dataSource.group({field:"myField", dir: sort[i].dir });
}
}
}
Kendo UI Grid Grouping gives you ListSortDirection.Ascending sorting by default. If you want to do something else you have to set it. If you are using the WebApi interface and generating a kendoRequest for the Kendo.mvc.dll method .ToDataSourceResult(kendoRequest); then you may try something like this:
var sort = kendoRequest.Sorts.FirstOrDefault();
var group = kendoRequest.Groups.FirstOrDefault();
if(sort != null && group != null) {
if(sort.Member == group.Member && sort.SortDirection == ListSortDirection.Descending) {
kendoRequest.Groups[0].SortDirection = sort.SortDirection;
}
}
var result = data.ToDataSourceResult(kendoRequest);
Related
Hi im relatively new to c# code and i was wondering if there is any way to get the amount of columns and rows in a grid and store that amount in a variable
Something like:
var columnamount = grid.columnamount;
But i could not find anything that works
Thanks
You can use the following code to get a count of the columns and rows directly via the ColumnDefinitions and RowDefinitions properties. No need to enumerate the children of the grid because you may not have views in every column/row.
var columnCount = grid.ColumnDefintions.Count;
var rowCount = grid.RowDefinitions.Count;
For reference the documentation.
You might be able to do it this way, purely based on what I see in the docs:
var countColumns = grid.Children.Where( c => c.Column).Max();
var countRows = grid.Children.Where( c => c.Row).Max();
But I'm not sure if you can access Row anf Column properties on the child element.
This is not the best way to check, I guess, but it's working (same thing for columns):
EDIT: nope, for columns it doesn't work
int GetRowsCount(Grid grid)
{
var item = grid.Children.FirstOrDefault();
return item != null ? Grid.GetRow(item) + 1 : 0;
}
I have a treeTable with editable cells within the expanded rows. The editable cells get a dirty flag after editing (in the example the background color is set to red).
The problem i'm running into is that i found no certain way to update the dirty flag on expand/collapse (edited cells get the css class 'edited-cell').
At the moment the code looks like that:
// each editable textfield gets a Listener
textField.attachLiveChange(
var source = oEvent.oSource;
...
jQuery('#' + source.getId()).addClass(EDITED_CELL_CLASS, false)
// list with cell ids, e.g. "__field1-col1-row1"
DIRTY_MODELS.push(model.getId()) //*** add also binding context of row
)
// the table rows are updated on toggleOpenState
new sap.ui.table.TreeTable({
toggleOpenState: function(oEvent) {
...
this.updateRows() // see function below
}
})
// update Rows function is also delegated
oTable.addDelegate({ onAfterRendering : jQuery.proxy(this.updateRows, oTable)});
//http://stackoverflow.com/questions/23683627/access-row-for-styling-in-sap-ui5-template-handler-using-jquery
// this method is called on each expand/collapse: here i can make sure that the whole row has it's correct styling...
// but how to make sure that special cells are dirty?
function updateRows(oEvent) {
if (oEvent.type !== 'AfterRendering'){
this.onvscroll(oEvent);
}
var rows = this.getVisibleRowCount();
var rowStart = this.getFirstVisibleRow();
var actualRow;
for (var i = 0; i < rows; i++){
actualRow = this.getContextByIndex(rowStart + i); //content
var row = this.getRows()[i]
var obj = actualRow.getObject()
var rowId = row.getId()
updateStyleOfRows(obj, rowId, actualRow)
updateDirtyCells(rowId) //*** how to get the binding context in this function???
}
};
// update Dirty Cells in function updateRows():
function updateDirtyCells(rowId){
for (var i = 0; i < DIRTY_MODELS.length; i++){
var dirtyCellId = DIRTY_MODELS[i]
//*** make sure that only the correct expanded/collapsed rows will be updated -> depends on the bindingContext of the row
jQuery('#' + rowId).find('#' + dirtyCellId + '.editable-cell').addClass(EDITED_CELL_CLASS, false)
}
}
This doesn't work correctly, because the ids of the cells change on each layout render (e.g. collapse/expand rows). Please see attached image.
Let me know if i should provide more information.
Have landed into a scenario.
I have a gridview with 22 static columns (few are BoundFields, few are TemplateFields).
We have a scenario in our project that we need to order the GridView according to the columns selected. The order of the columns selected is provided from the UI.
For ex: We have Doc1 to Doc23 as the columns.
Now, from the functionality provided in the UI, I am passing some 4 columns say Doc2,Doc4,Doc5,Doc7.
Now I want that only these 4 columns should be present in my grid as a final output.
Have tried some code, but it doesn't seem to work.
Below is my code:
public int GridColumnOrdering(string columnList)
{
string[] test = columnList.Split(';');
var docCatColumn = gridResultSet.Columns[0];
var docTypeColumn = gridResultSet.Columns[1];
int columnCount = 0;
int testCount = 0;
for (int i = 0; i < test.Count(); i++)
{
if (test[i] == "Doc2")
{
gridResultSet.Columns.Insert(i , docCatColumn);
columnCount++;
}
if (test[i] == "Doc3")
{
gridResultSet.Columns.Insert(i , docTypeColumn);
columnCount++;
}
}
gridResultSet.Columns[2].Visible = false;
gridResultSet.Columns[3].Visible = false;
}
columnList is a parameter passed which has values such as Doc2;Doc3.
My idea is that I get the static columns which resemble the column gotten from the UI, change its position to the very next position, and then hide that static column. In this way, we actually have 2 columns by the same name, but I am trying to hide the static one and display the dynamic one.
I know it sounds weird and hectic, but this is what came to my mind.
Now the problem is that if I try to change the visibility of the static column, the visibility of the dynamic one also changes.
Can experts help on this issue or point out to some easy method in this regards??
Regards
Anurag
I have a supposedly common problem to solve (done easily with other grid controls I'm familiar with).
In jqgrid, i'm quite stumped.
I have a jqgrid with inline editing enabled. I would like to add some scripting so that when editing a row (or adding a new row), the value of ColumnC is automatically computed as ColumnA * ColumnB as default. The user can change the values in any column at any time. I want this value to be computed as soon as the user enters it and not wait till the data is saved.
My approach so far has been to attach a dataEvent of type "change" to ColumnA and ColumnB -
dataEvents: [
{ type: 'change', fn: function(e) {
var rowid = $("#myGrid").jqGrid('getGridParam','selrow');
var rowData = $("#myGrid").getRowData(rowid);
var cell1 = rowData['ColumnA'];
var cell2 = rowData['ColumnB'];
var newValue = cell1 * cell2;
$("#myGrid").jqGrid('setCell', rowid, 'ColumnC', newValue);
}
},
]
Obviously, cell1 & cell2 don't actually return the value but the whole cell content as already discovered by other users here How to get a jqGrid cell value. The only way to get a cell value seems to be to use a custom regex user function that strips out that value.
Apart from that, is there a better/alternate way to achieve what I need? Something as simple as jqGrid - How to calculated column to jqgrid? though obviously that won't cut it for me since it will only displaying data and user cannot update it.
Any help would be appreciated.
UPDATE: After guidance from Oleg, I was able to extend getTextFromCell to support what I need.
function getTextFromCell(cellNode) {
var cellValue;
//check for all INPUT types
if (cellNode.childNodes[0].nodeName == "INPUT") {
//special case for handling checkbox
if (cellNode.childNodes[0].type == "checkbox") {
cellValue = cellNode.childNodes[0].checked.toString();
}
else {
//catch-all for all other inputs - text/integer/amount etc
cellValue = cellNode.childNodes[0].value;
}
}
//check for dropdown list
else if (cellNode.childNodes[0].nodeName == "SELECT") {
var newCell = $("select option:selected", cellNode);
cellValue = newCell[0].value;
}
return cellValue;
}
function getCellNodeFromRow(grid,rowId,cellName) {
var i = getColumnIndexByName(grid, cellName);
var cellValue;
//find the row first
$("tbody > tr.jqgrow", grid[0]).each(function() {
//The "Id" column in my grid is at index 2...
var idcell = $("td:nth-child(2)", this);
var currRowId = getTextFromCell(idcell[0])
if (currRowId == rowId) {
cellValue = getTextFromCell($("td:nth-child(" + (i + 1) + ")", this)[0]);
return false;
}
});
return cellValue;
}
The code in getCellNodeFromRow is not the most efficient. There is a .each() loop for find the matching row node. I can see this being slow when the grid has thousands of rows. Is there a better/more efficient way to find the row node? I have the row Id already.
Look at the demo from the answer. It uses cell editing, but the same technique work for inline editing too. Just click on any cell in the "Amount" column and modify the numerical value. You will see that the value in the "Total" row (footer) will be changed dynamically during the cell is still in the editing mode. I think it is what you need.
you can achieve this using onCellSelect event of jqgrid as below
//global section
var columnA;
var ColumnB;
var ColumnC;
var currentRow;
//
onCellSelect: function (rowid, iCol, aData) {
currentRow = rowid;
var ColumnA = $('#grid').getCell(rowid, 'MyCol');
var ColumnB = $('#grid').getCell(rowid, 'MyCol');
$("#grid").jqGrid('editRow', rowid, true );
$("#myMenu").hide();
if (rowid && rowid !== lastsel) {
if (lastsel) jQuery('#grid').jqGrid('restoreRow', lastsel);
$("#grid").jqGrid('editRow', rowid, true );
lastsel = rowid;
}
else if (rowid && rowid === lastsel)
{ $("#grid").jqGrid('editRow', rowid, true ); }
//if it is in editable mode
// when you view the html using firebug it will be like the cell id change to
//format like "rowid_ColumnName"
$('#' + currentRow + '_ColumnC').val(ColumnA*ColumnB);
// or you can use achieve this using following jqgrid method at
//appropriate place
$("#myGrid").jqGrid('setCell', rowid, 'ColumnC', ColumnA*ColumnB);
}
I have a 1 row, many column flex datagrid. I would like to turn the dataGrid on its side, so that the column headers become a single column running down and v.v.
Is there a way to do that in the DataGrid?
Or am I stuck manipulating the data presented to the grid? If so whats your recommendation?
The main idea here is I have an object like:
x=y
b=u
o=p
u=e
w=p
And I'd like a control that is visually similar to that. Currently the datagrid displays the object as:
x b o u w
y u p e p
Which is too horizontal for my case. Thx
I presume that you want to convert your columns in to a single column
this can be done by getting all the columns and put the in array as provide it as a dataprovider.
DataGrid.columns
will return the columns.
and you can do some think like this to create columns.
public function createColumns():Array{
var advancedDataGridColumn:AdvancedDataGridColumn;
var i:int;
var columnsArray:Array = new Array();
for(i=0;i<columns.length;i++){
advancedDataGridColumn=new AdvancedDataGridColumn();
advancedDataGridColumn.headerText=columns[i].dispheader.toString();
advancedDataGridColumn.dataField="#"+columns[i].name.toString();
advancedDataGridColumn.itemRenderer=new ClassFactory(Styler);
if(columns[i].descending!=undefined ){
if(columns[i].descending.toString()=="true")
sortField = new SortField("#"+columns[i].name.toString(),false,true,null);
else
sortField = new SortField("#"+columns[i].name.toString(),false,false,null);
}
if(advancedDataGridColumn.headerText == Constants.price||
advancedDataGridColumn.headerText == Constants.quantity||
advancedDataGridColumn.headerText == Constants.askPrice||
advancedDataGridColumn.headerText == Constants.bidPrice||
advancedDataGridColumn.headerText == Constants.netAmount||
advancedDataGridColumn.headerText == Constants.interestAmount||
advancedDataGridColumn.headerText == Constants.principalAmount||
advancedDataGridColumn.headerText == Constants.accruedInterestAmount){
var currencyFormattor:CurrencyFormatter = new CurrencyFormatter();
currencyFormattor.useThousandsSeparator=true;
currencyFormattor.currencySymbol="";
currencyFormattor.thousandsSeparatorFrom=",";
currencyFormattor.thousandsSeparatorTo=",";
advancedDataGridColumn.formatter=currencyFormattor;
}
columnsArray.push(advancedDataGridColumn);
}
return columnsArray;
}
sorry i just copied the code but i think it will help you.
Set the DataGrid to have only 2 columns and transform the original dataset to an array collection of {propName, propValue}.
Say you have:
var originalDataSet : ArrayCollection;
var dataSet : ArrayCollection;
var columnSet : ArrayCollection;
Once you have the original values, you'll do something like:
dataSet = new ArrayCollection();
for (var i : int; i < originalDataSet.length; i++)
{
dataSet.addItem({name : columnSet.getItemAt(i), value : originalDataSet.getItemAt(i)});
}
myDataGrid.dataProvider = dataSet;//set the data provider of the grid to the transformed data set.
To clarify:
{name : columnSet.getItemAt(i), value : originalDataSet.getItemAt(i)}
This creates a new instance of type Object and assigns the name and value dynamic properties to their respective values. Instead of this you might want to define your own class with bindable properties. Note that the property names are just for this example because I don't know what you're working with actually.
The data grid at that point should have two columns defined by you, with their dataField properties set accordingly. Also, this example assumes columnSet collection contains the "horizontal columns" that you want displayed vertically. If you can obtain these based on the values in the originalDataset, you might not even need columnSet.