Three level jQGrid only for some rows - jqgrid

I have a two level jqGrid (grid/subgrid) implementation that works very fine.
Now I have a requirement that push me to implement a third level subgrid in only some of the second level rows.
Is there any way to exclude the opening of the third level if any condition on the row does not permit it?
Thanks very much
EDIT as per #Oleg answer
I have implemented the more complex logic example as in the referenced answer, that is
loadComplete: function() {
var grid = $("#list");
var subGridCells = $("td.sgcollapsed",grid[0]);
$.each(subGridCells,function(i,value){
[...]
var rowData = grid.getRowData( ??? );
});
}
Can I use any field to retrieve the rowData in the each loop?

If I understand your question correctly you can do the same like I described in the answer, but do this on the second level of subgrids. To hide "+" icon in some rows you need just execute .unbind("click").html(""); on "td.sgcollapsed" elements of the second level subgrids.
UPDATED: The demo demonstrate how you can get rowid and use getLocalRow (alternatively getRowData) to hide selective subgrid icons ("+" icons). I used the following loadComplete code in the demo:
loadComplete: function () {
var $grid = $(this);
$.each($grid.find(">tbody>tr.jqgrow>td.sgcollapsed"), function () {
var $tdSubgridButton = $(this),
rowid = $tdSubgridButton.closest("tr.jqgrow").attr("id"),
rowData = $grid.jqGrid("getLocalRow", rowid);
if (rowData.amount > 250 ) {
$tdSubgridButton.unbind("click").html("");
}
});
}

Related

How to disable hyperlinks in jQGrid row

I am using a custom formatter to create hyperlinks in one of the columns of my grid.
In my code, there are cases when I need to disable the selected row. The row disabling works as I want it to, but the hyperlink for that row is not disabled. I can not select the row and all the other column values are displayed as grey colored to indicate that the row is disabled. The only column whose content does not change color is the one having links.
Any ideas on how to disable links?
This is my loadComplete function:
loadComplete: function (data) {
var ids =jQuery("#list").jqGrid('getDataIDs');
for(var i=0;i < ids.length;i++){
var rowId = ids[i];
var mod = jQuery("#list").jqGrid('getCell',ids[i],'mod');
if(mod=='y'){
jQuery("#jqg_list_"+rowId).attr("disabled", true);
$("#list").jqGrid('setRowData',ids[i],false, {weightfont:'bold',color:'silver'});
var iCol = getColumnIndexByName.call(this, 'adate');
$(this).jqGrid('doInEachRow', function (row, rowId, localRowData) {
$(row.cells[iCol]).children("a").click(function (e) {
e.preventDefault();
// any your code here
alert("No Good");
return false;
});
});
}
}
}
I want the links disabled in all the rows where the value of the column mod=y
You can try to use onClick callback of dynamicLink formatter described here, here and here. It gives you maximum flexibility. Inside of onClick callback you can test something like $(e.target).closest("tr.jqgrow").hasClass("not-editable-row") and just do nothing in the case.

How to change columns set of kendo grid dynamically

I am trying to change the columns collection of my Kendo grid in the below way.
var grid = $("#grid").data("kendoGrid");
$http.get('/api/GetGridColumns')
.success(function (data) {
grid.columns = data;
})
.error(function (data) {
console.log(data);
});
This is changing the column collection but not reflecting immediately in my grid. But when I try to perform some actions in the grid (like grouping), then my new column set is appearing.
Please let me know how can I achieve this.
Regards,
Dilip Kumar
You can do it by setting the KendoUI datasource, destroy the grid, and rebuild it
$("#load").click(function () {
var grid = $("#grid").data("kendoGrid");
var dataSource = grid.dataSource;
$.ajax({
url: "/Home/Load",
success: function (state) {
state = JSON.parse(state);
var options = grid.options;
options.columns = state.columns;
options.dataSource.page = state.page;
options.dataSource.pageSize = state.pageSize;
options.dataSource.sort = state.sort;
options.dataSource.filter = state.filter;
options.dataSource.group = state.group;
grid.destroy();
$("#grid")
.empty()
.kendoGrid(options);
}
});
});
here you can just do this :
var options = grid.options;
options.columns = state.columns;
where you can retrieve the columns in a session or in a db
This jsfiddle - Kendo UI grid dynamic columns can help you - using kendo.observable.
var columns = data;
var configuration = {
editable: true,
sortable: true,
scrollable: false,
columns: columns //set the columns here
};
var grid = $("#grid").kendoGrid(configuration).data("kendoGrid");
kendo.bind($('#example'), viewModel); //viewModel will be data as in jsfiddle
For the ones who are using Kendo and Angular together, here is a solution that worked for me:
The idea is to use the k-rebind directive. From the docs:
Widget Update upon Option Changes
You can update a widget from controller. Use the special k-rebind attribute to create a widget which automatically updates when some scope variable changes. This option will destroy the original widget and will recreate it using the changed options.
Apart from setting the array of columns in the GridOptions as we normally do, we have to hold a reference to it:
vm.gridOptions = { ... };
vm.gridColumns = [{...}, ... ,{...}];
vm.gridOptions.columns = vm.gridColumns;
and then pass that variable to the k-rebind directive:
<div kendo-grid="vm.grid" options="vm.gridOptions" k-rebind="vm.gridColumns">
</div>
And that's it when you are binding the grid to remote data (OData in my case). Now you can add or remove elements to/from the array of columns. The grid is going to query for the data again after it is recreated.
When binding the Grid to local data (local array of objects), we have to somehow postpone the binding of the data until the widget is recreated. What worked for me (maybe there is a cleaner solution to this) is to use the $timeout service:
vm.gridColumns.push({ ... });
vm.$timeout(function () {
vm.gridOptions.dataSource.data(vm.myArrayOfObjects);
}, 0);
This has been tested using AngularJS v1.5.0 and Kendo UI v2016.1.226.
I'm use this code for change columns dynamic:
kendo.data.binders.widget.columns = kendo.data.Binder.extend({
refresh: function () {
var value = this.bindings["columns"].get();
this.element.setOptions({ columns: value.toJSON });
this.element._columns(value.toJSON());
this.element._templates();
this.element.thead.empty();
this.element._thead();
this.element._renderContent(this.element.dataSource.view());
}
});
Weddin
Refresh your grid
.success(function (data) {
grid.columns = data;
grid.refresh();
})
Here is what i use
var columns = [];//add the columns here
var grid = $('#grid').data('kendoGrid');
grid.setOptions({ columns: columns });
grid._columns(columns);
grid._templates();
grid.thead.empty();
grid._thead();
grid._renderContent(grid.dataSource.view());
I think a solution for what you are asking is to call the equivalent remote DataSource.read() method inside of the function. This is what I used to change the number of columns dynamically for local js data.
$("#numOfValues").change(function () {
var columnsConfig = [];
columnsConfig.push({ field: "item", title: "Metric" });
// Dynamically assign number of value columns
for (var i = 1; i <= $(this).val(); i++) {
columnsConfig.push({ field: ("value" + i), title: ("201" + i) });
}
columnsConfig.push({ field: "target", title: "Target" });
columnsConfig.push({ command: "destroy", title: "" });
$("#grid").data("kendoGrid").setOptions({
columns: columnsConfig
});
columnDataSource.read(); // This is what reloads the data
});
Refresh the grid
$('#GridName').data('kendoGrid').dataSource.read();
$('#GridName').data('kendoGrid').refresh();
Instead of looping through all the elements. we can remove all the data in the grid by using a single statement
$("#Grid").data('kendoGrid').dataSource.data([]);
If your grid is simple and you don't need to configure special column-specific settings, then you can simply omit the columns argument, as suggested in the API reference.
Use autogenerated columns (i.e. do not set any column settings)
... and ....
If this [column] setting is not specified the grid will create a column for every field of the data item.
var newDataSource = new kendo.data.DataSource({data: dataSource}); $("#grid").data("kendoGrid").setDataSource(newDataSource);
$("#grid").data("kendoGrid").dataSource.read();
After fighting this for a day and seeing hints in this thread that Kendo had simplified this problem, I discovered you can just use setOptions with a single property.
.success(function (data) {
grid.setOptions({
columns: data,
});
})
Grid Set Options

Kendo - Grid - Remove Multiple Rows

I have the following code that remove rows that are checked (each row has a checkbox and I have a Filter button (and other buttons) in the toolbar).
var grid = $("#resultsGrid").data("kendoGrid");
grid.tbody.find("input:checked").closest("tr").each( function(index) {
grid.removeRow($(this));
});
However, performance starts to become an issue when there are > 20 rows being removed. However, kendo filters (removes) 20 rows or more much faster. How is kendo filtering removing multiple rows from the view? Or is there some other better way to remove multiple rows from the grid? Thanks in advance for your help.
** Updated Fiddle to new location - Same code as before **
Try dealing with the data directly. Have the checkbox hooked to the row's Id and filter on that.
I linked a fiddle that removes array elements and then re-creates the grid. The 2 text boxes at the top of the grid capture the range of Ids that you want to remove (this would be the same array of your checkboxIds). Then I cycled through those "remove Ids", removed them from the data array and remade the grid.
I slightly modified a previous fiddle and that's why I'm re-creating the grid instead of dealing with the DataSource object directly. But I hope you get the gist of what I'm doing.
I have 1000 records in this example (only 3 columns) but it removes 950 records very quickly.
Fiddle- Remove from data array
Let me know if you need an example of this with the KendoUI DataSource object.
I included this code below because StackOverflow wouldn't let me post without it.
function filterData() {
var val1 = $("#val1").val();
var val2 = $("#val2").val();
var removeIndexes = new Array();
for (var i = val1; i <= val2; i++) {
removeIndexes.push(i);
}
$(removeIndexes).each(function(removeIndex) {
var removeItemId = this;
$(randomData).each(function(dataIndex) {
var continueLoop = true;
if (this.Id == removeItemId) {
randomData.splice(dataIndex, 1);
continueLoop = false;
}
return continueLoop;
});
});
createGrid();
}
You should use batch updates:
$("#resultsGrid").kendoGrid({
dataSource: {
batch: true,
...
}, ...});
var grid = $("#resultsGrid").data("kendoGrid");
grid.tbody.find("input:checked").closest("tr").each( function() {
var dataItem = grid.dataItem(this);
grid.dataSource.remove(dataItem);
});
grid.dataSource.sync(); // this applies batched changes

jqGrid how can I hide subgrid if it empty?

How can i hide a subgrid if it empty?
I tried this solution and this but no luck.
Look at the old answer. It seems be exactly what you need.
Based on this and Oleg's answer i resolve my problem.
In my table all rows are expanded so code looks like this for main table:
gridComplete: function(){
var table_name = 'table_18';
var myGrid = $('#'+table_name);
var rowIds = myGrid.getDataIDs();
$.each(rowIds, function (index, rowId){
myGrid.expandSubGridRow(rowId);
});
var subGridCells = $("td.sgexpanded",myGrid[0]);
$.each(subGridCells,function(i,value){
$(value).unbind('click').html('');
});
}
In this code i removed click action for expand/collapse subgrids. So they are always open and there is no posibility to collapse them.
Based on this i remove empty subgrids.
loadComplete: function(){//in subgrid
var table_value = $('#'+subgrid_table_id).getGridParam('records');
if(table_value === 0){
$('#'+subgrid_id).parent().parent().remove();
}
}
Maybe exist more simple and elegant solution, but for me it's works as i expected.

Hide subgrid header in jqgrid

I have inplemented a JQGrid alog with a subgrid.
I have a requirement of hiding only the subgrid headers(the outer main grid headers should still be visible).
I tried using the following code $(".ui-jqgrid-hdiv", "#gbox_" + subgrid_id).hide() on subGridRowExpanded , which did not solve the problem.
Any help on this will be deeply appreciated.
Try to hide the header in the gridComplete function from the main grid:
gridComplete: function() {
var rowIds = $("#grid").getDataIDs();
$.each(rowIds, function (index, rowId) {
var subgridNameBasedOnRowId = "somesubgrid_" + rowId; //the name of my subgrid
$(".ui-jqgrid-hdiv", "#gbox_" + subgridNameBasedOnRowId).hide();
});
}

Resources