In my Kendo grid, I am trying to check if one of my column fields is true or false. If it is true, row should be expanded, if it is false, row should stay collapsed. My code definition for column is:
{
field: "Comment",
title: txt.TXT_COMMENT,
template: '<input type="checkbox" #= Comment ? "checked" : "" # disabled="false" ></input>',
},
My code condition in dataBound for checking if there is data:
dataBound: function (e) {
var data = this.dataItem;
if (data.Comment == 1) {
this.expandRow(this.tbody.find("tr.k-master-row"));
}
f_OnDataBound(e);
}
Thanks for your help!
You are on the right direction by using the databound event. What you need to do after it is, iterating through all the rows and check for a specific model property and expand, or not, that specific row.
var grid = $("#grid").data("kendoGrid");
var data = grid.dataSource.data();
var len = data.length;
for(var i = 0; i < len; i++) {
var row = data[i];
if(row.Comment == '1') { // checks for the value of the Comment property
grid.expandRow("tr[data-uid='" + row.uid + "']"); // expands the row with the specific uid
}
}
I tested this and works perfectly. I can't know what's on the Comment propery though, that's up to you to control and adapt the javascript function if needed.
EDIT
I have created a fiddle that demonstrates the above strategy. In the example the dataBound function looks for the property "name" and expands the row if it is "Sally"
Related
I'm using a kendo grid to display current values from a data source. Within the Kendo grid buttons are created to alter the values and display the change:
var grid = $("#Results").kendoGrid({
dataSource: resultsDS,
columns:
[{
title: "Drop Hammer",
field: "drop_hammer_bit",
width: 125,
filterable: false,
template: "<button type='button' class='btn pass-fail-btn' onclick='yes_btn_toggle($(this))'>#= drop_hammer_bit #</button>"
}]
}).data('kendoGrid');
function yes_btn_toggle(e) {
var txt = $(e).html();
if (txt == "No") {
$(e).removeClass('btn-secondary').addClass('btn-primary');
$(e).html("Yes");
$(e).value = "Yes";
} else {
$(e).removeClass('btn-primary').addClass('btn-secondary');
$(e).html("No");
}
}
There is a submit button which retrieves the Results data but it reflects data source and not the changes. I am struggling on understanding how to either A) correctly code the button click so that the submitted values are correctly or B) change how I can retrieve the altered data. So far my Submission function is this:
function submitQuality() {
var data = $("#Results").data();
var displayedData = $("#Results").data().kendoGrid.dataSource.view();
var cntr = displayedData.length;
var BatchQuality = new Array();
for (var i = 0; i < cntr; i++) {
var qualityObj = buildQuality(displayedData[i]);
BatchQuality.push(qualityObj);
}
}
Ultimately what I want to do is display the data source values of Yes/No and give the user the option to click a button to change its value. When they are ready they would click the Submit button to record the new changes. I feel like I am close to the answer but I lack the proper programming knowledge to weave it all syntactically.
I am not sure your requirement but i guess you are wondering to changed value yes to no and no to yes from kendo grid column button.
You will have to use refresh grid after changed value in the datasource.
$('#Results').data('kendoGrid').refresh()
Please let me know if code work for your.
On an asp.net mvc view, I have a Kendo UI treeview and a Kendo UI grid. Each checkbox in the treeview has the same id value in the ID column of the grid. Whenever I uncheck a checkbox in treeview I want to delete the corresponding row in the grid which has this id value. ID is one of the columns in the grid. The following is my code:
The following function is executed by the uncheck action on the treeview
function onCheck() {
var checkedNodes = [],
treeView = $("#treeview").data("kendoTreeView"),
var myNodes = treeView.dataSource.view();
for (var i = 0; i < myNodes.length; i++) {
var children = myNodes[i].children.view();
if (children) {
for (var j = 0; j < children.length; j++) {
if ((typeof children[j].checked !== undefined) && (!children[j].checked)) {
alert("You unchecked " + children[j].id); //This shows the correct id value
var dataItem = $("#grid").data("kendoGrid").dataSource.get(children[j].id);
$("#grid").data("kendoGrid").dataSource.remove(dataItem);
}
}
}
}
The following is the code for grid:
$("#grid").kendoGrid({
pageable:true,
dataSource: dataSource, //comes as json from a url
schema: {
model: {
id: "ID"
}
},
pageSize:3,
columns: [
{
hidden: true,
field: "ID"
},
{
field: "MyFileName"
},
});
When I debugged, the dataItem in var dataItem = $("#grid").data("kendoGrid").dataSource.get(children[j].id); comes as undefined. However the id the treeview retrieved and the id in the grid matched. This is the error I see: 0x800a138f - JavaScript runtime error: Unable to get property 'uid' of undefined or null reference
Obviously no grid row is deleted.
Thanks
Try this on your checkbox's change event:
var id = treeView.dataItem(this.closest("li")).id;
var gridDataItem = grid.dataSource.data().filter(function(item) {
return item.id == id;
})[0];
grid.removeRow('tr[data-uid="' + gridDataItem.uid + '"]');
The filter method will find the related row in the grid by the current id. Use grid's removeRow() insted of removing directly from dataSource.
Demo
i make simple application on titanium using table view. I have some custom row with checkbox on the left side. Here's my code :
var pickingData = [];
for (var i = 0; i<25; i++){
var row = Ti.UI.createTableViewRow({
className:'forumEvent', // used to improve table performance
backgroundSelectedColor:'cyan',
layout:'vertical'
});
if (Titanium.Platform.osname === 'android'){
var checkbox = Ti.UI.createSwitch({
style:Ti.UI.Android.SWITCH_STYLE_CHECKBOX,
value:false,
left:10
});
row.add(checkbox);
}
var rndMatNo = (randomInt(50000)+10000) //randomInt is my random number function
var lblMatNo = Ti.UI.createLabel({
realValue:rndMatNo,
text:'Mat No : ' + rndMatNo,
font:{fontFamily:'Arial', fontSize:DefaultFontSize, fontWeight:'bold'},
left:10,
color:'#222'
});
row.add(lblMatNo);
pickingData.push(row);
}
var tempPickingTable = Titanium.UI.createTableView({
data:pickingData,
editable: Titanium.Platform.osname === 'iphone' ? true : false,
name:'Picking table'
});
tempPickingTable.addEventListener('longclick',function(e){
for (var i=0, length=tempPickingTable.data[0].rows.length;i<length;i++){
if (tempPickingTable.data[0].rows[i].children[0].value === true){
tempPickingTable.deleteRow(i); //Still error when i'm using delete row because index out of bound
}
}
});
all i want is delete the row based on checkbox when it checked. i've tried looping for every row and check the checkbox and then delete the row, but it still give me error index out of bound.
has anyone know how to do that? thanks in advance..
There are some bugs in deleting rows from TableView in Android. You can try to create a new data array with all the rows except the ones that have been checked and then set the data for the tableview again.
You're iterating forward through the array, and deleting the rows, which modifies the array, so it makes sense that you'd go out of bounds. Have you tried iterating backwards?
tempPickingTable.addEventListener('longclick',function(e){
for (var i=tempPickingTable.data[0].rows.length;i>=0;i--){
if (tempPickingTable.data[0].rows[i].children[0].value === true){
tempPickingTable.deleteRow(i);
}
}
});
I have a scenario with grid within grid implemented using the detailInit method. Here when user makes edit, i do some calculations that will change the data in the both parent and child. and then to refresh data, i will call the datasource.read to render data. this works and the data is displayed, however any detail grid which are expanded will be collapsed, is there any way i can prevent this from happening.
To answer this and another question:
"I figured out how to set the data in the master from the child BUT, the
whole table collapses the child grids when anything is updated, this is a
very annoying behavior, is there anyway I can just update a field in
the master table without it collapsing all the child elements?
(basically, update the column, no mass table update)"
in another thread at: telerik
This is extremely annoying behavior of the Kendo Grid and a major bug. Since when does a person want the sub-grid to disappear and hide a change that was just made! But this isn't the only problem; the change function gets called a Fibonacci number of times, which will freeze the browser after a significant number of clicks. That being said, here is the solution that I have come up with:
In the main grid
$('#' + grid_id).kendoGrid({
width: 800,
...
detailExpand: function (e) {
var grid = $('#' + grid_id).data("kendoGrid");
var selItem = grid.select();
var eid = $(selItem).closest("tr.k-master-row").attr('data-uid')
if (contains(expandedItemIDs, eid) == false)
expandedItemIDs.push(eid);
},
detailCollapse: function (e) {
var grid = $('#' + grid_id).data("kendoGrid");
var selItem = grid.select();
var eid = $(selItem).closest("tr.k-master-row").attr('data-uid')
for (var i = 0; i < expandedItemIDs.length; i++)
if (expandedItemIDs[i] == eid)
gridDataMap.expandedItemIDs.splice(i, 1);
},
Unfortunately globally we have:
function subgridChange() {
var grid = $('#' + grid_id).data("kendoGrid");
for (var i = 0; i < expandedItemIDs.length; i++)
grid.expandRow("tr[data-uid='" + expandedItemIDs[i] + "']");
}
function contains(a, obj) {
for (var i = 0; i < a.length; i++)
if (a[i] === obj) return true;
return false;
}
expandedItemIDs = [];
Now the 'subgridChange()' function needs to be called every time a change is made to the subgrid.
The problem is that the number of times the change function in the subgrid gets called increases exponentially on each change call. The Kendo grid should be able to call a stop propagation function to prevent this, or at least give the programmer access to the event object so that the programmer can prevent the propagation. After being completely annoyed, all we have to do is to place the 'subgridChange()' function in the subgrid 'datasource' like so:
dataSource: function (e) {
var ds = new kendo.data.DataSource({
...
create: false,
schema: {
model: {
...
}
},
change: function (e) {
subgridChange();
}
});
return ds;
}
I also had to place the 'subgridChange()' function in the Add button function using something like this
$('<div id="' + gridID + '" data-bind="source: prodRegs" />').appendTo(e.detailCell).kendoGrid({
selectable: true,
...
toolbar: [{ template: "<a class='k-button addBtn' href='javascript://'><span class='k-icon k-add' ></span> Add Product and Region</a>" }]
});
$('.addBtn').click(function (event) {
...
subgridChange();
});
When a user selects a row, record the index of the selected row. Then after your data refresh, use the following code to expand a row
// get a reference to the grid widget
var grid = $("#grid").data("kendoGrid");
// expands first master row
grid.expandRow(grid.tbody.find(">tr.k-master-row:nth-child(1)"));
To expand different rows, just change the number in the nth-child() selector to the index of the row you wish to expand.
Actually all that is needed is the 'subgridChange()' function in the main grid 'dataBound' function:
$('#' + grid_id).kendoGrid({
...
dataBound: function (e) {
gridDataMap.subgridChange();
}
});
Different but similar solution that i used for same problem:
expandedItemIDs = [];
function onDataBound() {
//expand rows
for (var i = 0; i < expandedItemIDs.length; i++) {
var row = $(this.tbody).find("tr.k-master-row:eq(" + expandedItemIDs[i] + ")");
this.expandRow(row);
}
}
function onDetailExpand(e) {
//refresh the child grid when click expand
var grid = e.detailRow.find("[data-role=grid]").data("kendoGrid");
grid.dataSource.read();
//get index of expanded row
$(e.detailCell).text("inner content");
var row = $(e.masterRow).index(".k-master-row");
if (contains(expandedItemIDs, row) == false)
expandedItemIDs.push(row);
}
function onDetailCollapse(e) {
//on collapse minus this row from array
$(e.detailCell).text("inner content");
var row = $(e.masterRow).index(".k-master-row");
for (var i = 0; i < expandedItemIDs.length; i++)
if (expandedItemIDs[i] == row)
expandedItemIDs.splice(i, 1);
}
function contains(a, obj) {
for (var i = 0; i < a.length; i++)
if (a[i] === obj) return true;
return false;
}
I am new to jqGrid and I need help with a scenario that I am not able to figure out.
I am able to make a cell un-editable using the following code:
jQuery("#updAssist").jqGrid('setCell',rowid,'precPsProg','','not-editable-cell');
Now I want to make the cell editable again based on some condition.
What class should I use to achieve that?
Is there a 'editable-cell' class that I can use?
You should remove 'not-editable-cell' class from the cell (<td> element)
td.removeClass('not-editable-cell');
You should select all cells (<td> element) which you want make editable.
I made the demo which demonstrate how to do this. The most important code fragment from the demo is
var grid = $("#list");
var getColumnIndexByName = function(gr,columnName) {
var cm = gr.jqGrid('getGridParam','colModel');
for (var i=0,l=cm.length; i<l; i++) {
if (cm[i].name===columnName) {
return i; // return the index
}
}
return -1;
};
var changeEditableByContain = function(gr,colName,text,doNonEditable) {
var pos=getColumnIndexByName(gr,colName);
// nth-child need 1-based index so we use (i+1) below
var cells = $("tbody > tr.jqgrow > td:nth-child("+(pos+1)+")",gr[0]);
for (var i=0; i<cells.length; i++) {
var cell = $(cells[i]);
//var cellText = cell.text();
var unformatedText = $.unformat(cell,{rowId:cell[0].id,
colModel:gr[0].p.colModel[pos]},pos);
if (text === unformatedText) { // one can use cell.text() instead of
// unformatedText if needed
if (doNonEditable) {
cell.addClass('not-editable-cell');
} else {
cell.removeClass('not-editable-cell');
}
}
}
};
grid.jqGrid({
datatype: "local",
...
cellEdit: true,
cellsubmit: 'clientArray',
loadComplete: function() {
changeEditableByContain(grid,'name','test',true);
}
});
$("#doEditable").click(function(){
changeEditableByContain(grid,'name','test',false);
});
$("#doNonEditable").click(function(){
changeEditableByContain(grid,'name','test',true);
});
In the demo the cells from the 'Client' column having the text "test" will be marked as "non-editable". Later one can make the cells "editable" or "non-editable" be clicking on the corresponding button.