I'm trying to reload a jqGrid with new rows, colNames and colModel. The row data seems to load fine but the columns don't seem to be refreshed. I've tried using GridUnload and GridDestroy but I end up losing the jQuery DOM instance entirely and no longer loads any data as well.
var grid = $('#my-grid');
if(grid[0].grid == undefined) {
grid.jqGrid(options);
} else {
grid.setGridParam(options);
grid.trigger('reloadGrid');
}
The grid instance is important because it will be passed to other objects as a param. These objects may attach listeners or trigger events.
I'm using version 4.4.2
reloadGrid reload only the body of the grid and not changes the column headers which will be created when the grid was created.
If you need to change number of columns or to use colNames and colModel on place of old grid you have or recreate grid. You can use GridUnload method first and then create new grid (call grid.jqGrid(data) in your case). It's important that if you cached jQuery selector to grid in a variable like grid in your code you have to assign grid one more time after call of GridUnload, so you should do something like grid = $("#grid"); directly after call of GridUnload.
See the answer for more details and the code example.
It seems that jqGrid removes the initial <table></table> from the DOM and replaces it or forgets the reference (I haven't looked that hard into it).
So you have to reselect the new table everytime you want to create a new grid ie. $('table#my-grid'). This makes it tricky if you want to pass a reference of the grid's table about to other parts of your app as a parameter.
My work around involves deleting the grid reference and replacing the grid's wrapped div with the original table. then creating a jqGrid in the normal way with the new colModel and colNames.
grid.empty();
delete grid[0].grid;
$('#gbox_my-grid').replaceWith(grid);
grid.jqGrid(options);
It isn't the tidiest of solutions but it does allow me to keep a permanent reference to the original <table>. I'm uncertain how other jqGrid plugins will be affect by this though.
Edit
it turns out jQuery DataTables is better suited for customisation and we have adopted this instead of using jqGrid.
I have combined both answers and made some modification in order to have it to work.
var grid = $('#tableID');
if(grid[0].grid == undefined) {
grid.jqGrid(options);
} else {
delete grid;
$('#tableID').GridUnload('#tableID');
$('#tableID').jqGrid(options);
}
Related
I have a Datatable that uses static data from an HTML file.
Using either the "columnDefs data" function, or the "columnDefs render" function, I can perform some output adjustment - blanking out some of the TD's based on their content, and their position on the currently displayed page (without altering the data source).
However, when a user changes the number of displayed rows, I then need to reset & redo my adjustments on the data, as different cells will now need blanking, and previously blanked entries may need showing again.
So, what I want to do is in the "length.dt" event (number of display rows just changed), call something that causes the Datatable to either re-render the entire table, or re-load the entire data (which would thereby call my columnDefs render or columnDefs data functions)
Is this possible? Or is my approach flawed and I need to find another way?
Use rows().invalidate() to invalidate data for all rows and draw() to redraw the table.
Please note that 'data' in rows().invalidate('data') is required if you use Javascript data structure (with data or columns.render options).
$('#your_table').DataTable()
.rows().invalidate('data')
.draw(false);
You can redraw the entire DataTable on the length.dt event.
$('#your_table').on('length.dt', function (){
setTimeout(function() {
//draw('page') redraws your DataTable and preserves the page where it was
$('#your_table').DataTable().draw('page');
}, 100);
});
Edit
Here you can see more info and other parameters to pass to the draw method: https://datatables.net/reference/api/draw%28%29
Use 'destroy': true.
$("#your_table").dataTable({
'destroy': true
})
I have a button in each row, when pressed that row is removed from one table, and added to another table:
var row = $(this).closest("tr").remove().clone()
$('.my-other-table-class').append(row);
and at first it appears to work perfectly, the row is removed from one table and added to another, but when I force a re-draw (by changing the sorting of one of the columns, for example) all the rows are back as they were, and the buttons no longer work. This is the case for both the removed rows, and the rows added to the other table.
Is this because I'm using a .jsp table as a data-source? Would this work correctly if I dynamically added all the rows to the table using JavaScript at load-time, or if I used a modelMap collection as a data-source?
Thanks a lot for any advice.
Solution for future googlers - I have no idea how my google-Fu did not find the answer, I had all the right keywords!
In short:
I was doing this to add:
$('.my-other-table-class').append(row);
And this to remove:
var row = $(this).closest("tr").remove().clone()
but I should've been doing this add:
$('.my-other-table-class').dataTable().fnAddData([$(this).attr("data-val1"), "var2"]);
And this to remove:
$('.my-table').dataTable().fnDeleteRow($(this).closest('tr')[0]);
With more detail:
What I am really doing here is modifying the DOM with JQuery (well duh, but I'm really new at this, remember...) - I figured the DOM was the data-source for my table, so that made sense? The table is redrawn, it rereads the DOM and updates? Well not really.
In order to be dynamic, if you use DOM (in other words HTML, or in my case .jsp rendered as HTML) as your data-source, upon initialization, datatables will copy all that information into a JavaScript array.... so rather then my original thought:
"The DOM is not updating correctly, and that issues is propogating up in to my table... because HTML is static...or something?"
it turns out the actual problem was:
"I was updating the DOM, but the real data source was a JavaScript array I wasn't seeing. So upon redraw, this array was overwriting the DOM and my changes were being lost."
TL;DR: Use the Data-tables API and don't modify the data-source directly, unless you need to.
If the event handlers are one of the issues, it may help to set up your event handler like this:
$("#myTable").on("click", "button.moveMe", function(e) {
e.preventDefault();
var row = $(this).closest("tr").remove().clone()
$('.my-other-table-class').append(row);
});
This will set a handler on the table that has id="myTable". The handler will look for click events on buttons with the "moveMe" class. It will catch the event on rows that are added later, as well as the rows that exist when this hook is created.
Reference: http://api.jquery.com/on/
I'm attempting to input some values into the grid's new row template from outside the grid since selecting this particular input would be more than impractical to get done from inside de webdatagrid.
How can I reach the to be added row via javascript from outside the control? According to the documentation ig_controls.wdgTransaccion.get_behaviors().get_editingCore().get_behaviors().get_rowAdding().get_row(); should do the trick, but it fails to return any row at all
Thank you
Are you sure you calling this from the right place? Can't really tell without more context, however I think i can help you get the functionality you need. Have a look at this sample:
ASP.NET Data Grid: Add New Row - Client Events
The best place I can think of doing this is probably at the time of actual editing happening, so have a look at the EnteringEditMode event and you can do the following inside:
function WebDataGridView_EnteringEditMode(webDataGrid, evntArgs) {
webDataGrid.get_behaviors().get_editingCore().get_behaviors().get_rowAdding().get_row().get_cell("1").set_value("test");
}
Or if you want to do it on your own flow you can grab the grid client object and use the same code as the event above:
var webDataGrid = $find('<%=WebDataGrid1.ClientID%>');
webDataGrid.get_behaviors().get_editingCore().get_behaviors().get_rowAdding().get_row().get_cell("1").set_value("test");
Both of those methods work and allow you to fill in a cell value.
So this is a very specific question for SlickGrid, but I was wondering if anyone has ever tried to change the way the rows look when grouped? I was thinking that it would be cool to add a border around the grouped rows to show that they are part of that heading.
The way that SlickGrid works doesn't give any indication the rows are grouped in the DOM, they just appear under the header. I have tried to do something like this:
dataView.getItemMetadata = function(index) {
return {cssClasses: "myRowCssClass"};
}
but unfortunately, this broke other things in terms of the grouping. There is some stuff in the native getItemMetadata function that the groupBy function needs to process. I could copy that stuff into this function and add a condition for this, but that doesn't seem right. Does anyone who has some experience with SlickGrid know how to achieve this effect?
I know this is an old question. But I have done something similar to what you are asking about.
In my data, I have information about assets at several sites within an organization. So for each group of records, the name of the site will be the same. As I am reading my data (obtained via an $.ajax call), whenever the site name changes, I insert a 'parent' row in the data array.
I wanted to display these parent rows in bold. I accomplished this by defining a CSS class for the parent rows and using getItemMetadata() to apply the class.
dataView.getItemMetadata = function(row) {
if (row is a parent) {
return { 'cssClasses' : 'my-parent-row-class' };
}
};
In my application, I also made use of Slickgrid filters and a 'toggle' class (applied in a click handler) to implement a drill-down feature where you can click on a parent row and collapse/expand the rows grouped under that parent row.
I hope this helps.
Tim
I'm creating an extjs grid panel which has a user configurable set of columns. The Ext.grid.Panel component provides a handy reconfigure(store, columns) method for exactly this purpose.
This method works as expected to reconfigure a grid's store/columns without having to completely destroy and recreate the grid. However, if you are using the Ext.grid.plugins.RowEditing plugin to provide inline row editing, the columns get out of sync after the grid has been reconfigured with new columns.
This is particularly frustrating as the RowEditing plugin already watches for add/removing/resizing columns and handles those correctly. I suspect this is just an oversight in the current 4.1 release of ExtJs.
What I want is for the RowEditor to update its editors list and widths when the grid is reconfigured with new columns without destroying/recreating the grid/view.
After much googling it appears I am not alone in the search for an easily re-configurable column list with inline editing support.
The Ext.grid.Panel provides a 'reconfigure' event that is fired after any time the reconfigure() method is called. However, in the current 4.1 release of ExtJs the RowEditing plugin does not hook into this event!
It seems we need to do our own heavy lifting. The final solution is rather simple, although it took several hours to arrive at the final code.
The RowEditing plugin creates an instance of the RowEditor component (got it? keep those two seperate in your mind, similar names but different components!). The RowEditing plugin is what ties into the grid hooking into the necessary events to know when to show the row editor, etc.. The RowEditor is the visual component that popups over your row for inline editing in the grid.
At first I tried re-configuring the row editor probably a dozen different ways. I tried calling internal methods, init methods, resize methods, etc... Then I noticed something nice about the architecture. There is a single internal reference to the RowEditor instance with a method to fetch the row editor and lazy load if required. That was the key!
You can destroy the RowEditor without destroying the RowEditing plugin (you can't dynamically load/unload plugins) and then recreate the RowEditor.
There is one more catch, which is that the Editing plugins for the Ext grid add some extension methods to each column for getEditor() and setEditor() which are used to get/set the correct editor type for each column. When you reconfigure the grid, any applied extension methods are 'gone' (well you have some new columns that never had those methods applied). So you also need to re-apply those accessor methods by calling the initFieldAccessors() method on the plugin.
Here is my handler for the grid panel's reconfigure event:
/**
* #event reconfigure
* Fires after a reconfigure.
* #param {Ext.grid.Panel} this
* #param {Ext.data.Store} store The store that was passed to the {#link #method-reconfigure} method
* #param {Object[]} columns The column configs that were passed to the {#link #method-reconfigure} method
*/
onReconfigure: function (grid, store, columnConfigs) {
var columns = grid.headerCt.getGridColumns(),
rowEditingPlugin = grid.getPlugin('rowEditor');
//
// Re-attached the 'getField' and 'setField' extension methods to each column
//
rowEditingPlugin.initFieldAccessors(columns);
//
// Re-create the actual editor (the UI component within the 'RowEditing' plugin itself)
//
// 1. Destroy and make sure we aren't holding a reference to it.
//
Ext.destroy(rowEditingPlugin.editor);
rowEditingPlugin.editor = null;
//
// 2. This method has some lazy load logic built into it and will initialize a new row editor.
//
rowEditingPlugin.getEditor();
}
I attached this in my grid panel using a config listener:
listeners: {
'reconfigure': Ext.bind(this.onReconfigure, this)
}
It appears that this problem has since been corrected in the latest ExtJS versions - Version 4.1.1a at least integrates functionality similar to Ben Swayne's implementation.