Using a pure array as data source (not a DateView) to initialize a SlickGrid, I want to change a value after grid creation on a specific row / column (a cell).
Here is the simple example, that can also be found as a working JSFiddle and I want for example to change the value of "Duration" on row 3 ("Task 2") from "5 days" to "7 days".
<div id="myGrid" style="width:400px;height:400px;"></div>
<script>
var grid;
var columns = [
{id: "title", name: "Title", field: "title"},
{id: "duration", name: "Duration", field: "duration"},
{id: "%", name: "% Complete", field: "percentComplete"},
{id: "start", name: "Start", field: "start"},
{id: "finish", name: "Finish", field: "finish"},
{id: "effort-driven", name: "Effort Driven", field: "effortDriven"}
];
var options = {
enableCellNavigation: true,
enableColumnReorder: false
};
$(function () {
var data = [];
for (var i = 0; i < 500; i++) {
data[i] = {
title: "Task " + i,
duration: "5 days",
percentComplete: Math.round(Math.random() * 100),
start: "01/01/2009",
finish: "01/05/2009",
effortDriven: (i % 5 == 0)
};
}
grid = new Slick.Grid("#myGrid", data, columns, options);
grid.setSelectionModel(new Slick.CellSelectionModel());
/* needed method */
grid.setCellValue(2, 1, "7 days");
/* or */
grid.setCellValue(2, "duration", "7 days");
})
</script>
It looks like a method like
grid.setCellValue(row, column, value);
does not exist.
Is there a way (or existing method I didn't found yet) to achieve this without using a DataView?
Just use
data[2].duration = "7 Days";
and then refresh the grid:
grid.invalidateAllRows();
grid.render();
The grid only has display related helper methods, although you can get the data with grid.getData(). Editors, if you use them, contain code to extract the value from a row (data[n]) and write it to the editor UI, and then go back the other way.
I want to select rows in Kendo grid with shift+up/down arrow keys. Sample code is as below. If I set selectable property to 'multiple row' the 'keydown' event is not firing. If I set it to just 'row' it fires.
To me 'mutiple row' is needed because I want this funcitonality when user uses shift/ctrl with mouse to select multiple rows. Along with this if user wants to use only keyboard how can I select multiple rows?
You can find sample code here also fiddle
<div id="grid"></div>
$(document).ready(function() {
$("#grid").kendoGrid({
columns: [
{ field: "name" },
{ field: "age" }
],
dataSource: [
{ name: "Jane Doe", age: 30 },
{ name: "John Doe", age: 33 }
],
navigatable: true,
selectable: 'multiple row',
});
var data = $("#grid").data('kendoGrid');
//console.log(JSON.stringify(data));
var arrows = [37, 38, 39, 40];
data.table.on("keydown", function (e) {
console.log(e.keyCode);
//if (arrows.indexOf(e.keyCode) >= 0) {
if (e.shiftKey && (arrows.indexOf(e.keyCode) >= 0)){
console.log("shiftkey + arrow");
setTimeout(function () {
data.select($("#grid_active_cell").closest("tr"));
},1);
}
});
});
Consider I have a kendo grid like following
http://jsbin.com/uxumab/1/
It has ItemId, Qty, Price and Total(template) column.
I want to make Qty column editable and want to change total column value with the change of Qty column.
Finally I want to retrieve all the values with new changes using iteration through grid.
Basically the easiest way would be to do this through the MVVM of kendo. Here is an example:
$(document).ready(function () {
var gridData = [
{ ItemId: "1001", Qty: 2, price: 200 }
, { ItemId: "1002", Qty: 1, price: 100 }
, { ItemId: "1003", Qty: 1, price: 150 }
];
$("#grid").kendoGrid({
dataSource: gridData
, selectable: "row",
dataBound:function(){
grid = this;
grid.tbody.find('tr').each(function(){
var item = grid.dataItem(this);
kendo.bind(this,item);
})
}
, columns: [
{ field: "ItemId" }
, { field: "Qty" }
, { field: "price" }
, { title: "Quantity", width: "200", template: '<input data-role="numerictextbox" data-bind="value:Qty" data-max-value="100"/>' } , {
title: "Total"
, template: "#=Qty*price#"
}
]
});
});
And live version.
With the new kendo multiselect how would I add options to the list and make them selected?
For instance if I have a dropdown containing: 1,2,3 and I wanted to add 4 and 5 how do I do that? Do I have to destroy the multiselect, add the options and then reinit the multiselect?
Given the following multiselect definition:
var data =
[
{ text: "Africa", value: "1" },
{ text: "Europe", value: "2" },
{ text: "Asia", value: "3" },
{ text: "North America", value: "4" },
{ text: "South America", value: "5" },
{ text: "Antarctica", value: "6" },
{ text: "Australia", value: "7" }
];
var multi = $("#select").kendoMultiSelect({
dataTextField: "text",
dataValueField: "value",
dataSource: data
}).data("kendoMultiSelect");
You can use:
var values = multi.value();
For getting the list of values.
And for setting the value to South America (element with value 5) and "Asia" (element with value 3) use:
multi.value(["5", "3"])
If you want to add values to whatever it has then you need a little trick:
var multi = $("#select").kendoMultiSelect({
dataTextField: "text",
dataValueField: "value",
dataSource: data,
value: ["1", "2", "3"]
}).data("kendoMultiSelect");
// Adding value 4 and 5 to current content
var values = multi.value().slice();
$.merge(values, ["4", "5"]);
multi.value(values);
Warning: If values 4 and 5 were already selected you will end up having them duplicated.
Just want to add some information about how to actually add new values to the multi-select.
As OnaBai points out, the code to add an item to the multi-select is
$("#SDropDown").data("kendoMultiSelect").dataSource.add({ Text: x, Value: y });
given the .cshtml
#(Html.Kendo()
.MultiSelect()
.Name("SDropDown")
.AutoBind(true)
.Placeholder("Select s...")
.DataTextField("Text")
.DataValueField("Value")
)
In order to add an item as entered in the multi-select hook the change event for the text input. Since this isn't uniquely identified, I use XPath to get the <input> element. This is hooked in document.ready (in .cshtml, so escape #):
$(document).ready(function () {
var node = document.evaluate('//select[##id="SDropDown"]/../div[contains(##class,"k-multiselect")]/input', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
if (node)
{
node.onkeypress = SChanged;
}
}
function SChanged(e)
{
// only append on enter
if (kendo.keys.ENTER == e.keyCode)
{
// updates multi-select data source
AddToOrganizations(this.value);
var multi = $("#SDropDown").data("kendoMultiSelect");
multi.dataSource.filter({}); //clear applied filter before setting value
// keep all currently selected items and append the user entered text
// (does not check for duplicates)
// Also, the new values can only be selected after the data source has
// been updated.
var values = multi.value().slice();
$.merge(values, [this.value]);
multi.value(values);
}
}
Im currently working on a project which uses jqGrid with multiple subgrids. I'm trying to get the rowid (and get at the data within the row) when a row is clicked or double clicked. Eventually I would like to fill a text box with data from a clicked row.
I've tried a few variations using ondblClickRow and onSelectRow examples on here but wans't able to get it working. I think I'm missing something really simple but don't see what. So I went back and simplified it down as much as possible to just recognize the row click and display an alert. This won't work for me either.
(based on the example in jqGrid : issue loading nested sub grid with local datatype) Look for the //***************
part near the bottom..
var myData = [
// main grid data
{ id: "1", col1: "11", col2: "12",
subgrid: [
// data for subgrid for the id=m1
{ id: "1", c1: "aa", c2: "ab", c3: "ac",
subgrid: [
// data for subgrid for the id=m1, subgridId=s1a
{ id: "1", d1: "2aa", d2: "2ab", d3: "2ac" },
{ id: "2", d1: "2ba", d2: "2bb", d3: "2bc" },
{ id: "3", d1: "2ca", d2: "2cb", d3: "2cc" }
]},
{ id: "2", c1: "ba", c2: "bb", c3: "bc" },
{ id: "3", c1: "ca", c2: "cb", c3: "cc" }
]},
{ id: "2", col1: "21", col2: "22",
subgrid: [
// data for subgrid for the id=m2
{ id: "1", c1: "1xx", c2: "1xy", c3: "1xz",
subgrid: [
// data for subgrid for the id=m2, subgridId=s2a
{ id: "1", d1: "2xx", d2: "2xy", d3: "2xz" }
]}
]},
{ id: "3", col1: "31", col2: "32" }
],
removeSubgridIcon = function () {
var $this = $(this),
idPrefix = $this.jqGrid("getGridParam", "idPrefix");
$this.find(">tbody>tr.jqgrow>td.ui-sgcollapsed").filter(function () {
var rowData = $this.jqGrid("getLocalRow",
$.jgrid.stripPref(idPrefix, $(this).closest("tr.jqgrow").attr("id")));
return rowData.subgrid == null;
}).unbind("click").html("");
},
isHasSubrids = function (data) {
var l = data.length, i;
for (i = 0; i < l; i++) {
if (data[i].subgrid != null) {
return true;
}
}
return false;
},
specificGridOptions = [
{
colNames: ["Column 1", "Column 2"],
colModel: [
{ name: "col1" },
{ name: "col2" }
],
cmTemplate: { width: 200 },
sortname: "col1",
sortorder: "desc",
idPrefix: "s_",
pager: "#pager",
caption: "Demonstrate how to create subgrid from local hierarchical data"
},
{
colNames: ["Colunm1", "Colunm2", "Colunm3"],
colModel: [
{ name: "c1" },
{ name: "c2" },
{ name: "c3" }
],
cmTemplate: { width: 112 },
sortname: "c1",
sortorder: "desc"
},
{
colNames: ["Col 1", "Col 2", "Col 3"],
colModel: [
{ name: "d1" },
{ name: "d2" },
{ name: "d3" }
],
cmTemplate: { width: 90 },
sortname: "d1",
sortorder: "desc"
}
],
commonGridOptions = {
datatype: "local",
gridview: true,
rownumbers: true,
autoencode: true,
height: "100%",
//***************
onSelectRow : function ()
{
alert('test!');
},
//also tried many variation on this
ondblClickRow: function(rowid)
{
alert(rowid);
}
//***************
loadComplete: function () {
// one can use loadComplete: removeSubgridIcon, but I included
// curent implementation of loadComplete only to show how to call
// removeSubgridIcon from your loadComplete callback handler
removeSubgridIcon.call(this);
},
subGridRowExpanded: function (subgridDivId, rowId) {
var $subgrid = $("<table id='" + subgridDivId + "_t'></table>"),
subgridLevel = $(this).jqGrid("getGridParam", "subgridLevel") + 1,
parentIdPrefix = $(this).jqGrid("getGridParam", "idPrefix"),
pureRowId = $.jgrid.stripPref(parentIdPrefix, rowId),
localRowData = $(this).jqGrid("getLocalRow", pureRowId);
$subgrid.appendTo("#" + $.jgrid.jqID(subgridDivId));
$subgrid.jqGrid($.extend(true, {}, commonGridOptions, specificGridOptions [subgridLevel], {
data: localRowData.subgrid,
subGrid: isHasSubrids(localRowData.subgrid),
subgridLevel: subgridLevel,
idPrefix: rowId + "_",
rowNum: 10000 // we use this to have no pager in the subgrids
}));
}
};
$("#list").jqGrid($.extend(true, {}, commonGridOptions, specificGridOptions[0], {
data: myData,
subgridLevel: 0,
subGrid: isHasSubrids(myData)
}));
Anyone have any ideas why it won't recognize the row click/double click?
You wrote in comment that you get the data for the grid from the server. I suppose that the usage of datatype: "local" in the case is not the best choice. Look at the answer where I described the way how to do the same, but using datatype: "json".
Now I come back to your main question. I don't understand what text box (HTML input element) you want to fill and whether the input element is inside of the grid or outside of it. Nevertheless the only problem which you could probably have is the correct usage of idPrefix option of jqGrid.
It's very important to understand, that jqGrid use HTML <table> for representing of the body of grids. Every <tr> element of the <table> must have id attribute in the current implementation of jqGrid. So the id property from the input data will be used to assign the value of id attribute of <tr> elements. If one has more as one grid on the page or if one has grid with subgrids it's very easy to receive id duplicates which not allowed in all versions of HTML or XHTML.
Additional potential problem is the usage of numbers as id values. The most databases support auto-incremental datatype which is very practical as the key of the tables. In the case the native id (the key) for the database table and for the grid rows will be integer numbers. On the other side there are some additional restrictions depend on the version of HTML/XHTML which one uses. For example HTML5 specification says (see here)
The value must be unique amongst all the IDs in the element's home
subtree and must contain at least one character. The value must not
contain any space characters.
So even though the most web browsers allows to use numbers as the values of id attribute it's not permitted and one can get compatibility problems in case of usage of this.
To solve all the described above problem jqGrid supports idPrefix options (which was introduced by the way based on my suggestion). In the case the value of id attribute will be build as concatination of idPrefix and the id from the input data. For example in case of idPrefix: "s_" and id values "1", "2", "3" used in the main grid of the example jqGrid will assign "s_1", "s_2", "s_3" as values of id attribute of <tr> elements of the main grid. The rowid of all callbacks will be the value from id attribute ("s_1", "s_2", "s_3"). If you need get the original id you can use $.jgrid.stripPref to strip the prefix. All ids which will be sent to the server by jqGrid will be normalized ($.jgrid.stripPref will be called) by jqGrid itself.
So the code which shows how to get data onSelectRow and ondblClickRow could be the following
onSelectRow: function (rowid, stat, e) {
myDebugTrace.call(this, "onSelectRow", rowid);
},
ondblClickRow: function (rowid, iRow, iCol, e) {
myDebugTrace.call(this, "ondblClickRow", rowid);
e.stopPropagation();
},
...
where myDebugTrace function can be declared as
var myDebugTrace = function (startingText, rowid) {
var $this = $(this), p = $this.jqGrid("getGridParam"), rowData, col1,
firstCol = (p.rownumbers ? 1 : 0) + (p.subGrid ? 1 : 0);
rowData = $this.jqGrid("getRowData", rowid);
col1 = rowData[p.colModel[firstCol].name];
$("<span>" + startingText + " on " + rowid + " (original id=" +
$.jgrid.stripPref($(this).jqGrid("getGridParam", "idPrefix"), rowid) +
"). Data from the first column: \"" + col1 +"\"</span><br/>").appendTo("body");
};
The corresponding demo display the following on double-click on the row from the internal subgrid.