Kendo grid button click arguments - kendo-ui

I have a kendo grid with a button column. When the button is clicked, I want it to call a javascript function with the row's data as parameters. Here's what I have so far
$(grd).kendoGrid({
dataSource: ds,
detailInit: detailInit,
columns: [ {field: "foo", title: "bar" },
{field: "Y" },
{command: { text: "MyButton", click: doStuff } } ]
});
function doStuff(e)
{
//e is click events but I want to pass in data from the row instead
//following is code I found here but item is null for me
var row = $(this).closest("tr");
var item = $(grd).data("kendoGrid").dataItem(row);
}

This will give you the data pertaining to the row which the button was clicked.
function doStuff(e) {
var tr = $(e.target).closest("tr"); // get the current table row (tr)
var item = this.dataItem(tr); // get the date of this row
alert(item.PropertyName);
}

Related

kendo multiselect values disappear when in editor mode

I have a master-child setup and in my child grid rows, I have a multi-select that uses a list of strings as datasource. When I click to add/remove entries, the already selected items disappear completely and I can only see the drop down with all the values.
Here is the grid column definition in the child grid:
field: "Teams",
title: "Team",
editor: ChildItemEditor,
Here is the editor function that creates the multi-select:
...
var dataSource = ["Item A" , "Item B"];
...
function ChildItemEditor(container, options)
{
$('<select multiselect="multiselect" id="ddlItems" name="childItems" data-bind="value:' + options.field + '" />')
.appendTo(container)
.kendoMultiSelect({
autoBind: false,
dataSource: dataSource,
select: function (e) {
var dataItem = this.dataItem(e.item.index());
var selectedItem = this.gridMasterData.dataItem(this.gridMasterData.select());
if (selectedItem == null) {
return false;
}
options.model.Items = this.value();
$(selectedItem.Items).each(function (i, cItem) {
if (options.model.Id == cItem.Id) {
cItem.Items= options.model.Items;
selectedItem.dirty = true
}
});
},
});
}
Found the issue: When reading back data, the second field had a leading space and Multiselect did not automatically Trim the field to bind to it.

Remote update cell content in kendo grid

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

How to programmatically create a new row and put that row in edit mode in Kendo grid

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;
}

How to get row index and cell index of row click kendo grid

I have added onchange event for kendo-ui grid.
In that I am trying to get the ID value for that particular row. I have added an image column as first column in the grid. What I want is when the image is clicked, I want to open a image url.
So, basically what I want is that when I click the row, I want to get the clicked row index and also I want to get the clicked cell Index in that row.
So based on the row clicked and if it is not the first cell clicked, I want to display alert. If I the first cell is clicked I want to open image.
How can I get this index.
I have set selectable : row in the kendo-ui grid
Please help me on this.
Please try with below code snippet.
function onDataBound(e) {
var grid = $("#Grid").data("kendoGrid");
$(grid.tbody).on("click", "td", function (e) {
var row = $(this).closest("tr");
var rowIdx = $("tr", grid.tbody).index(row);
var colIdx = $("td", row).index(this);
alert(rowIdx + '-' + colIdx);
});
}
$(document).ready(function () {
$("#Grid").kendoGrid({
dataSource: {
type: "odata",
transport: {
read: "http://demos.kendoui.com/service/Northwind.svc/Orders",
dataType: "jsonp"
},
schema: {
model: {
fields: {
OrderID: { type: "number" },
Freight: { type: "number" },
ShipName: { type: "string" },
OrderDate: { type: "date" },
ShipCity: { type: "string" }
}
}
},
pageSize: 10,
serverPaging: true,
serverFiltering: true,
serverSorting: true
},
dataBound: onDataBound,
filterable: true,
sortable: true,
pageable: true,
columns: [{
field: "OrderID",
filterable: false
},
"Freight",
{
field: "OrderDate",
title: "Order Date",
width: 120,
format: "{0:MM/dd/yyyy}"
}, {
field: "ShipName",
title: "Ship Name",
width: 260
}, {
field: "ShipCity",
title: "Ship City",
width: 150
}
]
});
});
<div id="Grid"></div>
If all you need is knowing the row and column index in the table you can do:
$(grid.tbody).on("click", "td", function(e) {
var row = $(this).closest("tr");
var rowIdx = $("tr", grid.tbody).index(row);
var colIdx = $("td", row).index(this);
console.log("row:", rowIdx, "cell:", colIdx);
});
Where I set a click handler for clicking in the cells of the grid.
Then I find to which row (<tr>) that cell belongs to using jQuery closest.
Next use jQuery index for finding the index of that row in the table.
Do the same for finding the cell index inside the row.
But maybe there are simpler ways as detecting if the user clicked on an image, or set some CSS class in the image and then check if the clicked cell has that class,...
EDIT If in addition you want to retrieve the original item inside the click handler. Add
var item = grid.dataItem(row);
From there, you can get id or any other field for validation.
Example here : http://jsfiddle.net/OnaBai/MuDX7/
Kendo has introduced frozen columns since the question has been answered so I think it deserved a little update to deal with that feature.
When you have a frozen column, the grid will create new header / content tables to manage the frozen columns. If you freeze a column, it will move item linked to this column from the regular grid's tbody / thead to the lockedContent / lockedHeader (the opposite is also true).
If you get the index using the accepted answer, you'll get the index of the cell within the tbody (or -1 if the cell is frozen). The real question is what do you want to do with the column index? If you really want an index number, you may have to adjust the value by adding the number of columns in the lockedContent depending on your needs. However, if your final goal is to get the grid's column object, this can be done by using the th element:
var row = cell.closest("tr");
var body;
var header;
if (cell.closest(grid.lockedContent).length) {
body = grid.lockedContent;
header = grid.lockedContent;
} else {
body = grid.tbody;
header = grid.thead;
}
var rowIndex = $("tr", body).index(row);
var columnIndex = $("td", row).index(cell);
var columnField = header.find("th").eq(columnIndex).attr("data-field");
var column;
$.each(grid.columns, function () {
if (this.field === columnField) {
column = this;
return false;
}
});
Disclaimer: just to add a level of complexity, you should also consider that kendo has also introduced a multiple column header feature that may invalidate my code above.
For the cell index, kendo grid has a method cellIndex(cell)
var cell = $("#grid td:eq(1)");
console.log(grid.cellIndex(cell));

Display hyperlink value in kendo ui grid column

I have created columns dynamically in the kendo ui grid. The data displayed in the columns could be date , string integer, hyperlinks or any other type.
Data in the column can be integer/hyperlink at the same time. Means for a particular record the data in column can be integer. For next record same column can have a hyperlink value.
I have created fields and added that in the grid.
How can I do this.
You can always set a function against the template of the column you wish to format and conditionally return the content of what you want to appear.
This could look something like this:
var dataSource = new kendo.data.DataSource({
data: [
{ Id:1, val: "value" },
{ Id:"http://google.com", val: "another value" }
]
});
$(function () {
$("#grid").kendoGrid({
columns: [
{
field: "Id",
template: function (dataItem) {
if (typeof dataItem.Id == "string") {
return "" + dataItem.Id + "";
} else {
return dataItem.Id;
}
}
}],
dataSource: dataSource
});
});

Resources