I have a Kendo Grid and I want to detect the right click and left click, so based on these I do two separate things. I used to get ID from the grid on either left or right click before and was working fine. But to fix an IE11 clicking problem I had to update the kendo.js to 2013.2.716 version and after that it detects left/right click all right but for "Right Click" can't get the selected row Id. The following is my code to detect left/right click and PlodId is a column in my grid:
function LoadMainShiftGrid() {
//For Right Click --> Delete Selected Shift
$("#shiftReport").delegate("tbody>tr", "contextmenu", function (e) {
if (e.which == 3) {
$("#plodDetails").hide();
var gridData = $('#shiftReport').data("kendoGrid");
var selectedRowData = gridData.dataItem($('.k-grid').find("tr.k-state-selected"));
// MY PROBLEM FOR RIGHT CLICK SELECTEDROWDATA COMES TO NULL <<<<
var SelectedPlodId = selectedRowData.PlodId;
}
});
//For Left Click --> Show Plod Detials
$("#shiftReport").delegate("tbody>tr", "click", function (e) {
if (e.which == 1) {
var gridData = $('#shiftReport').data("kendoGrid");
var selectedRowData = gridData.dataItem($('.k-grid').find("tr.k-state-selected"));
var SelectedPlodId = selectedRowData.PlodId;
}
});
}
Thank you in advance.
I've changed the click binding function to 'mousedown' and select the row manually (Thank you #drw85 for the idea) and after that it works fine.
function LoadMainShiftGrid() {
$('#shiftReport').data('kendoGrid').tbody.on('mousedown', function (e) {
//select the clicked row manually; this resolves all problem :D
$('#shiftReport').data("kendoGrid").select(e.target.parentElement);
if (e.which == 3) {
$("#plodDetails").hide();
var gridData = $('#shiftReport').data("kendoGrid");
var selectedRowData = gridData.dataItem($('.k-grid').find("tr.k-state-selected"));
var SelectedPlodId = selectedRowData.PlodId;
}
//For Left Click --> Show Plod Details
if (e.which == 1) {
var gridData = $('#shiftReport').data("kendoGrid");
var selectedRowData = gridData.dataItem($('.k-grid').find("tr.k-state-selected"));
var SelectedPlodId = selectedRowData.PlodId;
}
});
}
I think that happens, because the right click doesn't actually select the row.
You can select it through code, before you try to get it via
var selectedRowData = gridData.dataItem($('.k-grid').find("tr.k-state-selected"));
You should be able to get the click target through the event object and set the selected property on it via kendo.
var index = gridData.find(e.delegateTarget).index();
var dataItem = gridData.dataSource.view()[index];
dataItem.selected();
You might have to pass true to the selected function.
You can also get the selected row like this..
$("#shiftReport").on("mousedown", "tr[role='row']", function (e) {
if (e.which === 3) {
$(this).addClass("k-state-selected");
var gview= $('#shiftReport').data("kendoGrid");
var selectedRow = gview.dataItem($(this));
}
});
Use .Selectable() will high light the row when you hover over rows and click on any particular row, sample code:
#(Html.Kendo().Grid(Model)
.Name("Grid")
.DataSource(datasource => datasource
.Ajax()
.ServerOperation(false)
.PageSize(15)
)
.Sortable()
.Columns(columns =>
{
columns.Bound(model => model.NetworkID);
columns.Bound(model => model.FirstName);
columns.Bound(model => model.LastName);
})
.Filterable()
.Scrollable(s => s.Height(550))
.Pageable()
.Resizable(resize => resize.Columns(true))
.Selectable()
)
In IE 11 this will work
$("#grid").kendoGrid({
change: function(e) {
var selected = this.select();
var selectedDataItems = [];
for (var i = 0; i < selected.length; i++) {
var dataItem = this.dataItem($(selected[i]).closest("tr"));
selectedDataItems.push(dataItem);
}
}
});
Related
Here I have a code to update a cell contet when pressing a button.
It works fine, but it doesn't set the flag, that indicates, that the cell has been changed.
It should look like this with the litle red triangle:
The code:
<a id="button" href="#">Click me</a>
<div id="grid"></div>
<script>
var dataSource, grid;
$(document).ready(function () {
dataSource = new kendo.data.DataSource({
data: [
{ category: "Beverages", name: "Chai", price: 18},
{ category: "Seafood", name: "Konbu", price: 6}
],
})
grid = $("#grid").kendoGrid({
dataSource: dataSource,
editable: true,
}).data("kendoGrid");
$('#button').click(function (e) {
var data = grid.dataItem("tr:eq(1)");
data.set('category', 'Merchandice');
});
});
</script>
Update:
Here is the update based on #tstancin: Kendo example.
Thank you for the answer - I had thought of it to.
I am wondering if it's possible to do the update in a more clean way with some binding through som MVVM perhaps?
Kind regards from Kenneth
If that's all you want then you should expand your button click code with the following:
$('#button').click(function (e) {
var data = grid.dataItem("tr:eq(1)");
data.set('category', 'Merchandice');
$("#grid tr:eq(1) td:eq(1)").addClass("k-dirty-cell");
$("#grid tr:eq(1) td:eq(0)").prepend("<span class='k-dirty'></span>");
});
But if you, for instance, manually change the value of name column from Chai to something else, and then click the click me button, the dirty marker in the name column will disappear.
You should use flags for every cell and set them before data.set(). Then, in the grid's dataBound event you should inspect every cell's value and assign the dirty marker if it's needed. For manual changes you should handle the save event and set flags there.
I wrote a script that makes it posible to use a call like this:
SetCellData(id, columnName, value);
So with an id, a columnName and a value, I can update a value in a grid and the flag will be set on the cell.
function SetCellData(id, columnName, value) {
var dataItem = grid.dataSource.get(id);
dataItem.set(columnName, value);
var columnIndex = GetColumnIndex(columnName);
if (columnIndex > -1) {
var cell = $('tr[data-uid*="' + dataItem.uid + '"] td:eq(' + columnIndex + ')')
if (!cell.hasClass("k-dirty-cell")){
cell.prepend("<span class='k-dirty'></span>");
cell.addClass("k-dirty-cell");
}
}
}
function GetColumnIndex(columnName) {
var columns = grid.columns;
for (var i = 0; i < columns.length; i++)
if (columns[i].field == columnName)
return i;
return -1;
};
I have the code here : example
In my Kendo grid I am trying to put the 'create new item' button in the header (title) of the command column instead of the toolbar. Here is part of my grid definition:
var grid = $("#grid").kendoGrid({
columns: [{ command: { name: "edit", title: "Edit", text: { edit: "", cancel: "", update: "" } },
headerTemplate: "<a onclick ='NewItemClick()' class='k-button k-button-icontext k-create-alert' id='new-item-button' title='Click to add a new item'><div>New Item</div></a>"},
My question is: how to create a new row and put that row in edit mode in 'NewItemClick()'
There are some troublesome scope issues when you try to bind the click event in the template definition itself.
Instead, it is easier to assign the link an ID, and then bind the click event later. Notice that I've given it id=create.
headerTemplate: "<a id='create' class='k-button k-button-icontext k-create-alert' id='new-item-button' title='Click to add a new item'><div>New Item</div></a>"
Then in document ready, I bind the click event:
$("#create").click(function () {
var grid = $("#grid").data("kendoGrid");
if (grid) {
//this logic creates a new item in the datasource/datagrid
var dataSource = grid.dataSource;
var total = dataSource.data().length;
dataSource.insert(total, {});
dataSource.page(dataSource.totalPages());
grid.editRow(grid.tbody.children().last());
}
});
The above function creates a new row at the bottom of the grid by manipulating the datasource. Then it treats the new row as a row "edit". The action to create a new row was borrowed from OnaBai's answer here.
Here is a working jsfiddle, hope it helps.
I would like to complete on gisitgo's answer. If your datasource takes some time to update, when calling page(...), then the refresh of the grid will cancel the editor's popup. This is averted by binding the call to editRow to the "change" event :
var grid = $("#grid").data("kendoGrid");
if (grid) {
//this logic creates a new item in the datasource/datagrid
var dataSource = grid.dataSource;
var total = dataSource.data().length;
dataSource.insert(total, {});
dataSource.one("change", function () {
grid.editRow(grid.tbody.children().last());
});
dataSource.page(dataSource.totalPages());
}
NB: This approach will yield problems if your grid is sorted because the new row will not necessarily be at the end
I have found that issues might appear if you have multiple pages, such as the inserted row not opening up for edit.
Here is some code based on the current index of the copied row.
We also edit the row based on UID for more accuracy.
function cloneRow(e) {
var grid = $("#grid").data("kendoGrid");
var row = grid.select();
if (row && row.length == 1) {
var data = grid.dataItem(row);
var indexInArray = $.map(grid.dataSource._data, function (obj, index)
{
if (obj.uid == data.uid)
{
return index;
}
});
var newRowDataItem = grid.dataSource.insert(indexInArray, {
CustomerId: 0,
CustomerName: null,
dirty: true
});
var newGridRow = grid.tbody.find("tr[data-uid='" + newRowDataItem.uid + "']");
grid.select(newGridRow);
grid.editRow(newGridRow);
//grid.editRow($("table[role='grid'] tbody tr:eq(0)"));
} else {
alert("Please select a row");
}
return false;
}
I have checkbox in Kendo grid. Once i click on Checkbox it always focus the top cell in Kendo Grid. Below is code for Kendo grid that I am binding to checkbox value on checkbox click event in Kendo Grid
$("#contactgrid").on('click', '.chkbx', function () {
var checked = $(this).is(':checked');
var grid = $('#contactgrid').data().kendoGrid;
var rowIdx = $("tr", grid.tbody).index(row);
var colIdx = $("td", row).index(this);
// grid.tbody.find("tr").eq(rowIndex).foucs(); This doesn't work
var dataItem = grid.dataItem($(this).closest('tr'));
dataItem.set('IsSelected', checked);
});
I can get the row index and cell Index in click event but I was not able to figure out to focus the specific cell.
Thanks!
When you want to edit Grid with checkbox then I would suggest you to use the approach from this code library. No matter it uses the MVC extensions open Views/Home/Index.cshtml and see how the template is defined and the javascript used after initializing the Grid.
Here it is
Column template:
columns.Template(#<text></text>).ClientTemplate("<input type='checkbox' #= IsAdmin ? checked='checked':'' # class='chkbx' />")
.HeaderTemplate("<input type='checkbox' id='masterCheckBox' onclick='checkAll(this)'/>").Width(200);
<script type="text/javascript">
$(function () {
$('#persons').on('click', '.chkbx', function () {
var checked = $(this).is(':checked');
var grid = $('#persons').data().kendoGrid;
var dataItem = grid.dataItem($(this).closest('tr'));
dataItem.set('IsAdmin', checked);
})
})
function checkAll(ele) {
var state = $(ele).is(':checked');
var grid = $('#persons').data().kendoGrid;
$.each(grid.dataSource.view(), function () {
if (this['IsAdmin'] != state)
this.dirty=true;
this['IsAdmin'] = state;
});
grid.refresh();
}
</script>
I struggled with this. I essential refocused the cell as shown below. There's plenty of room for improvement in the Kendo grid client-side API. Hopefully my helper methods below will help people out.
var $row = getRowForDataItem(this);
var $current = getCurrentCell($row);
var currentCellIndex = $row.find(">td").index($current);
this.set('PriceFromDateTime', resultFromDate);
$row = getRowForDataItem(this);
var grid = getContainingGrid($row);
//select the previously selected cell by it's index(offset) within the td tags
if (currentCellIndex >= 0) {
grid.current($row.find(">td").eq(currentCellIndex));
}
//Kendo grid helpers
function getColumn(grid, columnName) {
return $.grep(grid.columns, function (item) {
return item.field === columnName;
})[0];
}
function getRowForDataItem(dataItem) {
return $("tr[data-uid='" + dataItem.uid + "']");
}
function getCurrentCell($elem) {
return getContainingGrid($elem).current();
}
function getContainingDataItem($elem) {
return getDataItemForRow(getContainingRow($elem));
}
function getContainingCell($elem) {
return $elem.closest("td[role='gridcell']");
}
function getContainingRow($elem) {
return $elem.closest("tr[role='row']");
}
function getContainingGrid($elem) {
return $elem.closest("div[data-role='grid']").data("kendoGrid");
}
function getGridForDataItem(dataItem) {
return getContainingGrid(getRowForDataItem(dataItem));
}
function getDataItemForRow($row, $grid) {
if (!$grid) $grid = getContainingGrid($row);
return $grid.dataItem($row);
}
function getMasterRow($element) {
return $element.closest("tr.k-detail-row").prev();
}
function getChildGridForDataItem(dataItem) {
return getRowForDataItem(dataItem).next().find("div.k-grid").data("kendoGrid");
}
function getMasterRowDataItem($element) {
var $row = getMasterRow($element);
return getDataItemForRow($row);
}
I need to change the row color of a kendo ui grid depending on a particular condition. I am using server side bindings with MVC. My code is as follows,
var grid = Html.Kendo().Grid<AllocateCOESGridViewModel>();
grid.Name("AllocateResultGrid")
.RowAction(row =>
{
if (row.DataItem.COESNo == 13054915)
{
row.HtmlAttributes["style"] = "background:blue";
}
else
{
row.HtmlAttributes["style"] = "background:red";
}
})
.Columns(columns =>
{
columns.Bound(s => s.COESNo).Title(#Allocate.COESGridHeading);
columns.Bound(s => s.Street).Title(#Allocate.StreetGridHeading);
columns.Bound(s => s.Suburb).Title(#Allocate.SuburbGridHeading);
columns.Bound(s => s.Postcode).Title(#Allocate.PostcodeGridHeading);
columns.Bound(s => s.InspectorName).Title(#Allocate.InspectorGridHeading);
columns.Bound(s => s.COESNo).Title(#Allocate.AllocateGridHeading + "<input type ='checkbox' id ='SelectAll' />").ClientTemplate("<input type ='checkbox' data-id='#= COESNo #' class='allocate' />").Sortable(false);
});
The grid works but no row colors at all? no blue or red.. I just get the standard white and grey.. any thoughts?
Thanks
This is how I got this to work, just wondering if there is any other options, as looping through the grid seems like a not so good idea... especially if the grid is long
var grid = $("#AllocateResultGrid").data("kendoGrid");
grid.bind("dataBound", updateGridRows);
updateGridRows: function()
{
dataView = this.dataSource.view();
for (var i = 0; i < dataView.length; i++)
{
if (dataView[i].Selected == false)
{
var uid = dataView[i].uid;
$("#AllocateResultGrid tbody").find("tr[data-uid=" + uid + "]").addClass("customClass");
}
}
}
I added the customClass in my stylesheet
I had the same issue, let me know if you find one without loops!
var grid = $("#AllocateResultGrid").data("kendoGrid");
var data = grid.dataSource.data();
$.each(data, function (i, row) {
if (row.Selected == false)
$('tr[data-uid="' + row.uid + '"] ').addClass("customClass");
}
I want to get the selected row "ID" but it just failed... and i have totally no clue what is happening here.
MVC HTML Code :
#(Html.Kendo().Grid(Model)
.Name("grid")
.HtmlAttributes(new { style = "margin-top: 5px" })
.Columns(c =>
{
c.Bound(model => model.mgID);
c.Command(com => { com.Custom("Edit").Click("Edit");});
})
.Pageable()
.Sortable()
.Selectable()
.DataSource(d => d
.Ajax()
.PageSize(20)
.Model(model => model.Id(i => i.mgID))
.Read(r => r.Action("Manage_Read", "Manage"))
.Destroy(o => o.Action("Manage_Destroy", "Manage"))
)
)
Javascript Code :
function Edit() {
var grid = $("#grid").data("kendoGrid");
var row = grid.select();
var selectedRowIndex = row.index(); //Return "-1"
var dataItem = grid.dataItem(row); //Return "Undefined"
}
Please tell me, what am i miss out??
If all you need is get the dataItem of the row containing the clicked "Edit" button, you can use:
function Edit(e) {
var dataItem = this.dataItem($(e.target).closest("tr"));
}
NOTE:
in the context of click event this is the grid.
in that same context e.target is your button, so we look for the closest table row.