Get clicked cell on kendo ui grid change event - kendo-ui

I am handling the change event of the kendo ui grid.
In the event handler, I would like to get the cell that was clicked that invoked the change event. I need the cell in order to scan its contents.
Any thoughts?

It's actually very well documented in the documentation: http://docs.telerik.com/kendo-ui/api/web/grid#events-change
Here's the example code if you have the grid configured for multiple cell selection (selectable: "multiple, cell"):
change: function(e) {
var item;
var selected = this.select(); //get selected cell(s)
for (var i = 0; i < selected.length; i++) {
item = this.dataItem(selected[i].parentNode); //get selected cell's dataItem
}
}

In order to select the table cell that was clicked to edit, simply use e.container. There are a number of options given from the event handler. Here's a few:
change: function (e) {
//jQuery object containing the cell
var cell = e.container;
//jQuery object containing the input
var field = cell.find("input");
//value in the input
var fieldVal = field.val();
//or, on one line:
fieldVal = e.container.find("input").val();
//also, if you happen to want the data model for that row
var model = e.model;
}

Related

Row selection dynamically for next page and reverse back in kendo grid

Anyone please tell me how can i select next consecutive row from first page to second page of my kendo grid and reverse back to the previous page ? Kendo Grid API just only gives me information on 'select' and from there I have no clue at all how to implement my desired selection. What I have now is only selecting the row of the selected/active cell. Any insight/references are also appreciated. So far I haven't came across with any examples or article.
var data = $("#grid").data('kendoGrid');
var arrows = [38,40];
data.table.on("keydown", function (e) {
if (arrows.indexOf(e.keyCode) >= 0) {
setTimeout(function () {
data.clearSelection();
data.select($("#grid_active_cell").closest("tr"));
},1);
}
});
http://dojo.telerik.com/eSUQO
var data = $("#grid").data('kendoGrid');
var arrows = [38,40];
var navrow_uid; ** add this tracking variable;
data.table.on("keydown", function (e) {
if (arrows.indexOf(e.keyCode) >= 0) {
setTimeout(function () {
data.clearSelection();
// break this up
// data.select($("#grid_active_cell").closest("tr"));
// fetch next row uid and compare to tracker
var nextrow = $("#grid_active_cell").closest("tr");
var uid = nextrow.data('uid');
if (navrow_uid == uid ) {
console.log("last navigable row");
data.dataSource.page(1+data.dataSource.page());
// best option here would be to set auto-page flag for databound event handler
} else {
data.select(nextrow);
navrow_uid = uid;
}
},1);
}
});
You will want to add a grid data bound handler, and have that check the aut-page flag to see if you need to select first or last row of page.

Adding External filters for Kendo UI Grid

What i want to achieve is:
Have a Master Grid. Clicking on a row of this grid, i want to filter the rows of the ChildGrid.
What i have done so far:
function updateChildGridRows(field, operator, value) {
// get the kendoGrid element.
var gridData = $("#childGrid").data("kendoGrid");
var filterField = field;
var filterValue = value;
// get currently applied filters from the Grid.
var currFilterObj = gridData.dataSource.filter();
// if the oject we obtained above is null/undefined, set this to an empty array
var currentFilters = currFilterObj ? currFilterObj.filters : [];
// iterate over current filters array. if a filter for "filterField" is already
// defined, remove it from the array
// once an entry is removed, we stop looking at the rest of the array.
if (currentFilters && currentFilters.length > 0) {
for (var i = 0; i < currentFilters.length; i++) {
if (currentFilters[i].field == filterField) {
currentFilters.splice(i, 1);
break;
}
}
}
if (filterValue != "") {
currentFilters.push({
field: filterField,
operator: "eq",
value: filterValue
});
}
gridData.dataSource.filter({
filters: currentFilters
}); }
I got this code from the following jsfiddle:
http://jsfiddle.net/randombw/27hTK/
I have attached the MasterGrid's Change event to MasterGridSelectionChange() method. From there i am calling my filter method.
But when i click on the MasterGrid's row, all of the rows in my ChildGrid are getting removed.
One thing i can understand is, if i give wrong column name in the filter list, all the rows will be removed. But even though i have given correct ColumnName, my rows are getting deleted.
Sorry for the long post.
Please help me with this issue, as i am stuck with this for almost 4 days!
Thanks.
You can define ClientDetailTemplateId for the master grid and ToClientTemplate() for the Child grid
read Grid Hierarchy for a example

How to get Active (focused) slickgrid?

I have two slickgrid and one delete button,
When i click on delete,i want focused grid so that i will delete items.
How to get focused grid ?
This is what i have done so far....
function deleteRow(e, args){
//code to delete items from "grid"
var selectedrows = grid.getSelectedRows();
var len = selectedrows.length;
var itemNo = "";
for(var i=0;i<len;i++)
{
var data = grid.getData().getItem(selectedrows[i]);
dataView.deleteItem(data.id);
itemNo =data.id;
var url = "delete_Item_Master?itemNo="+itemNo;
$.get(url, {itemNo : itemNo},function(data) {
location.reload(true);
});
}
//code to delete items from "metalGrid"
var metalSelectedrows = metalGrid.getSelectedRows();
var mlen = metalSelectedrows.length;
var itemNo = "";
for(var i=0;i<mlen;i++)
{
var mData = metalGrid.getData().getItem(metalSelectedrows[i]);
meyalDataView.deleteItem(mData.id);
itemNo =mData.id;
var url = "delete_subItem?itemNo="+itemNo;
$.get(url, {itemNo : itemNo},function(data) {
location.reload(true);
});
}
}
But this code delete items from both grid..
I think that the correct way to do this is to write your own selection model. It should be a Singleton, and two grids should interact with it. It should know which grid was last active.
But you need to ask yourself is that behaviour is good. What if user will delete an item from another grid - because there's only one button. IMHO every grid should have it's own button. And I work for an ERP company where we got that dillemas everyday ;)

Retain expanded rows after databinding Kendo UI grid

This is my first time working with Kendo UI. I have a Kendo UI grid with child nodes. I want to retain the expanded rows after databinding. Right now its getting collapsed after a row is added in the child
I have tried suggestion from here
dataBound: function() {
this.expandRow(this.tbody.find("tr.k-master-row").first());
}
But this expands the first row only.
How to retain rows? What am I missing?
Codepen
After a lot of playing around with your code example in CodePen, I believe I've come up with an elegant solution that works.
Having worked with Kendo UI for over three years, I've become pretty familiar with some of its inner workings. As such, I'm going to take advantage of one of these - the data-uid attribute. Kendo UI puts these on all <tr> elements in its grid. I chose this attribute because I know that when we call grid.expandRow() we're going to need to fashion a valid jQuery selector to pass in as a parameter. This eliminates the need for us to add our own attributes or classes and the code to handle them.
First, we need to define a variable to hold our row reference. We'll call it expandedRowUid. To set its value, we hook into the detailExpand event of the grid. So, when the user expands a row, we store its data-uid number.
var expandedRowUid;
var grid = $('#grid').kendoGird({
// ...
detailExpand: function(e) {
expandedRowUid = e.masterRow.data('uid');
}
});
Then, whenever a change is made that causes the master grid to re-bind to its data, we hook into the dataBound event of the grid and re-expand the row that has a data-uid equal to the one stored in expandedRowUid.
var grid = $('#grid').kendoGird({
// ...
detailExpand: function(e) {
expandedRowUid = e.masterRow.data('uid');
},
dataBound: function() {
this.expandRow($('tr[data-uid=' + expandedRowUid + ']'));
}
});
Here is the working CodePen example.
NOTE: This will only re-expand the last row that was expanded before the data bind is triggered. So, if you expand rows 4, 5, and 2 in that order, and then trigger a data bind, only row 2 will be re-expanded. You can obviously extend this functionality to handle use cases like that though.
GridDetailExpand: function (e) {
var gridId = e.sender.element[0].id;
var grid = $("#" + gridId).data("kendoGrid");
var data = grid.dataItem(e.masterRow);
addToArray(expandedRows, data.UniqueIdOfYourDataInGrid);
},
GridDetailCollapse: function (e) {
var gridId = e.sender.element[0].id;
var grid = $("#" + gridId).data("kendoGrid");
var data = grid.dataItem(e.masterRow);
removeFromArray(expandedRows, data.UniqueIdOfYourDataInGrid);
}
And then on databound
var gridId = e.sender.element[0].id;
var grid = $("#" + gridId).data("kendoGrid");
$.each(grid.tbody.find('tr.k-master-row'), function () {
var data = grid.dataItem(this);
if (isInArray(expandedRows, data.UniqueIdOfYourDataInGrid)) {
grid.expandRow(this);
}
});
Functions required:
var expandedRows = [];
function addToArray(arr, value) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] === value) return;
}
arr.push(value);
}
function removeFromArray(arr, value) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] === value) {
delete arr[i];
return;
}
}
}
function isInArray(arr, value) {
for (var i = 0; i < arr.length; i++) {
if (arr[i] === value) return true;
}
return false;
}
Hope this helps ... took me a while to figure it out...
Solution for Retaining Last Expanding row in the parent grid after records added in the child grid get refreshed.
detailInit: function (e) {
//Get Parent Grid Last expanded Row index
lastRowIndex = $(e.masterRow).index(".k-master-row");
},
dataBound: function () {
//Check any parent grid row is expanded based on row index
if (lastRowIndex != null && lastRowIndex != undefined){
//find the Grid row details based on row index
var row = $(this.tbody).find("tr.k-master-row:eq(" + lastRowIndex + ")");
//If expand Row exists then it will expanded
this.expandRow(row);
}
else {
//None of the Parent Grid row is expanded then,default First row is expanded
this.expandRow(this.tbody.find("tr.k-master-row").first());
}
}

Assigning functions to multiple slickgrids

Please help to solve this very annoying problem. I am using a for loop to iterate over an array of data and create multiple grids. It is working well but the filter function is not binding properly (it only binds to the LAST grid created) Here is the code:
// this function iterates over the data to build the grids
function buildTables() {
// "domain" contains the dataset array
for (i = 0; i < domains.length; i++) {
var dataView;
dataView = new Slick.Data.DataView();
var d = domains[i];
grid = new Slick.Grid('#' + d.name, dataView, d.columns, grids.options);
var data = d.data;
// create a column filter collection for each grid - this works fine
var columnFilters = columnFilters[d.name];
// this seems to be working just fine
// Chrome console confirms it is is processed when rendering the filters
grid.onHeaderRowCellRendered.subscribe(function (e, args) {
$(args.node).empty();
$("<input type='text'>")
.data("columnId", args.column.id)
.val(columnFilters[args.column.id])
.appendTo(args.node);
});
// respond to changes in filter inputs
$(grid.getHeaderRow()).delegate(":input", "change keyup", function (e) {
var columnID = $(this).data("columnId");
if (columnID != null) {
// this works fine - when the user enters text into the input - it
// adds the filter term to the filter obj appropriately
// I have tested this extensively and it works appropriately on
// all grids (ie each grid has a distinct columnFilters object
var gridID = $(this).parents('.grid').attr('id');
columnFilters[gridID][columnID] = $.trim($(this).val());
dataView.refresh();
}
});
//##### FAIL #####
// this is where things seem to go wrong
// The row item always provides data from the LAST grid populated!!
// For example, if I have three grids, and I enter a filter term for
// grids 1 or 2 or 3 the row item below always belongs to grid 3!!
function filter(row) {
var gridID = $(this).parents('.grid').attr('id');
for (var columnId in grids.columnFilters[gridID]) {
if (columnId !== undefined && columnFilters[columnId] !== "") {
var header = grid.getColumns()[grid.getColumnIndex(columnId)];
//console.log(header.name);
}
}
return true;
}
grid.init();
dataView.beginUpdate();
dataView.setItems(data);
dataView.setFilter(filter); // does it matter than I only have one dataView instance?
dataView.endUpdate();
grid.invalidate();
grid.render();
In summary, each function seems to be binding appropriately to each grid except for the filter function. When I enter a filter term into ANY grid, it returns the rows from the last grid only.
I have spent several hours trying to find the fault but have to admit defeat. Any help would be most appreciated.
yes, it matters that you have only one instance of dataView. and also sooner or later you will come up to the fact that one variable for all grids is also a bad idea
so add a var dataView to your loop, it should solve the problem

Resources