My JqGrid looks like this:
Staff
Room 1
Room 2
Jim
240
120
Dave
480
240
The staff and rooms are obtained from tables and are unknown in number at runtime. The figures (data) represent the total time spent by each staff in each room and are in minutes. I have all the above working.
All I want to do now is to iterate over all the data entries and change minutes (Eg: 240) to hours and minutes (EG 4h:0m). I'm ok with doing the math for the conversion, it's the looping over the cells and the reading and updating (just the displayed value) that has defeated me.
This is my code so far for the looping:
var $grid = jQuery('#statstab1grid')
var rows = $grid[0].rows
var crows = rows.length
var irow, row, cellsofrow
for (irow = 1; irow < crows; irow++)
{
row = rows[irow];
cellsofrow = row.cells;
alert('$(cellsofrow[0]).text() is ' + $(cellsofrow[0]).text())
alert('$(cellsofrow[1]).text() is ' + $(cellsofrow[1]).text())
}
The first alert outputs Jim then Dave, the second alert outputs nothing,
just the prompt. Even if I managed to access the data values, how would I write back to the grid the modified values?
It is good to post which version of jqGrid is used. This one is the important part.
The code you posted and your comments that nothing is alerted for cell index 1, can tell me that maybe you have a hidden field in your colModel, which value is empty. In this case it would be good to post your entire grid setup.
To the problem - you have a lot of options to do this conversion.
You can use custom formatter - more about this you can find here. This method is preferred.
You can use getRowData (without parameter) to get all the data in the grid and use setRowData to update the values. Be a careful with this method if you have a lot of data in the grid - it will be slowly in this case. See docs for grid methods
If your data is local (array) you can recalculate it, before to put it into the grid
HandsonTable is not rendering all rows - it loads only part of all rows. But when I do Ctrl+A and paste into Excel I see all the rows. Why is Handsontable not displaying all the rows?
<hot-table col-headers="true" row-headers="true" datarows="data" context-menu width="1080">
<hot-column ng-repeat="column in columns" data="{{column.data}}"></hot-column>
</hot-table>
To render all rows, just set renderAllRows: true
The current answer does not answer the original question.
Handsontable does not render all cells at once because it is designed to be efficient for very large data sets. It does this using virtual rendering, dynamically modifying the DOM to include only the cells at the scroll position.
The rows virtual rendering can be disabled by setting renderAllRows: true, as described in the docs: "If typed true then virtual rendering mechanism for handsontable will be disabled." Although it will then not be as efficient for large data sets.
You can also change the number of pre-rendered rows and columns instead of rendering them all. From the performance tips,
You can explicitly specify the number of rows and columns to be rendered outside of the visible part of the table. In some cases you can achieve better results by setting a lower number (as less elements get rendered), but sometimes setting a larger number may also work well (as less operations are being made on each scroll event). Tweaking these settings and finding the sweet spot may improve the feeling of your Handsontable implementation.
This is done by setting viewportRowRenderingOffset and viewportColumnRenderingOffset in the handsontable options. These are by default set to auto which lets handsontable try to find the best value, but may be provided an integer value (e.g. viewportRowRenderingOffset: 70, viewportColumnRenderingOffset: 70).
I had the same problem (using HandsOnTable 6.2.1 and the old AngularJS) and customers would start complaining about not being sure if they were at the end of the table or not.
I was able to create two buttons linked to the functions 'scrollToBeginning' and 'scrollToEnd'. This way the user is sure to be at the last line. Three things specific about my answer:
I expose the functions to the DOM using $scope;
I have an object 'goToLine' holding 3 properties (scrollingToEnd: boolean, row: number, col: number), it is used in other functions not posted here;
I have a list of ID referencing HandsOnTable objects stored in $scope.hots.
Here is my raw solution, feel free to adapt / enhance:
$scope.stopScrollingToEnd = function () {
$scope.goToLine.scrollingToEnd = false;
};
$scope.scrollToBeginning = function (goToLine) {
$scope.stopScrollingToEnd();
const hot = $scope.hots[goToLine.id];
hot.scrollViewportTo(0, 0);
};
/**
* Scroll to the end of the List Element.
* We need this functionality because of a bug in HandsOnTable related to its Virtualization process.
* In some cases (complex table), when manually scrolling, the max row is wrong, hence causing major confusion for the user.
* #param {*} goToLine
* #returns
*/
$scope.scrollToEnd = function (goToLine) {
// We scroll to the first line before going to the last to avoid the bug and being sure we get to the last line
$scope.scrollToBeginning(goToLine);
const hot = $scope.hots[goToLine.id];
var numberOfRows = hot.countRows();
// This variable is used to repeat the scrollViewportTo command.
// It is built using the length of `numberOfRows`.
var repeat = numberOfRows ? 1 * Math.ceil(Math.log10(numberOfRows + 1)) : 1;
// Used in other goTo function to avoid conflict.
$scope.goToLine.scrollingToEnd = true;
// FIXME : not supposed to call scrollViewportTo several times... => fixed in recent versions of HandsOnTable ?
for (let n = 0; n < repeat; n++) {
if (!$scope.goToLine.scrollingToEnd) {
return;
}
setTimeout(function () {
if (!$scope.goToLine.scrollingToEnd) {
return;
}
hot.scrollViewportTo(numberOfRows - 1, 0);
}, 500);
}
};
I use standart Ext.grid.Panel in extJs.
I need to select up to 500 rows in grid, and I want to know how many rows I have selected. I do it in such way:
multiSelect: true,
listeners:
{
'select':
function( combo, record)
{
mainNS.app.pagingTB.items.get('selected-sited').update(' count of selected rows: ' +
mainNS.app.mainGrid.getSelectionModel().getCount())
}
},
But it works too slow, how can I optimize this operation?
The select event will fire for every record during a multiple selection. So if n rows are being selected at once, that means you're updating the content and, most importantly, triggering a layout n times.
You have 2 options:
Listen to the selectionchange event, which will fire only once for a batch of selections.
Add buffer: 1 as an option to the select event, so it will buffer the event from firing until the last selection has occurred.
No. 1 is the preferred solution.
I have a large list where I've implemented filtering. I'd like to user to be able to select some rows, filter the list, select a few more, change the filter, select more, and have all of the selections remain.
I am following this example:
http://mleibman.github.com/SlickGrid/examples/example4-model.html
Follow these steps to see my problem:
Click on the 0 row
Shift-click on the 10 row. Rows 0 through 10 are selected now.
Move the slider up to about 90%, so only a few of the rows 0 - 10 show. (For me, 2, 6, and 8 still show and are still selected.)
Ctrl-click on an un-selected row (for me, row 29)
Slide the filter back down to zero.
Now this issue is seen. For me, only rows 2, 6, 8, and 29 are selected. I would prefer that 0 through 10 and 29 remain selected. Is there an option to get this behavior? If not, can someone recommend an approach that might work?
This problem has been solved on Github.
First, add a variable to store id.
var selectedIds=[];
Second, modifiy syncGridSelection
DataView.syncGridSelection(grid, true, true, function(syncIds) { selectedIds = syncIds;});
The trick is to:
Save some indication for every selected row
As you build the filtered data, note which lines are selected in an array
Call "setSelectedRows" after "setGridData"
Here is code that does it.
// filter grid without harming selection
// grid: a SlickGrid Object
// filter: a function that receieves a "data row" and returns true if it meets the filter
function filterGrid(grid,filter) {
var oldline;
var olddata=grid.getData();
var oldselection=grid.getSelectedRows()
var newline=0;
var newdata=[];
var newselection=[];
for (oldline=0; oldline<olddata.length ; oldline++ ) {
if (filter(olddata[oldline]) {
newdata.push(olddata[oldline]);
if (oldselection.indexOf(oldline)>-1) { // note on condition: ECMA5 - in IE8 you will need to loop
newselection.push(newline);
newline++;
}
}
}
grid.setData(newdata);
grid.setSelectedRows(newselection);
grid.updateRowCount();
grid.render();
}
Note that this code DOES NOT preserve selected rows which do not pass the filter.
I have more than 1000 rows to populate data through jqGrid. When I populate data through jqGrid, jqGrid takes more than 20 seconds to populate data. This time is taken only by jqGird (query execution time and other time is excluded). I have a requirement to populate 1000 rows by using jqGrid and I don't want to use Pagination. Please help me how to increase the performance of jgGrid.
The versions we are using are:
jgGrid: 3.6.4
jQuery:1.4.2
jQuery UI:1.7.2
Browser: IE 7
Following is the code:
jQuery("#displayItemPerformanceGrid").jqGrid({
//datatype: displayItemPerformanceGridData, //json
url:'/DISMGMT/StandardProxy/displayItemPerformanceService?userRole='+userRole+
'&userName='+userName+'&duration='+displayDuration+'&userId='+userId,
datatype: 'json',
colNames: ["CM","Display Location","Display Name","Item","Item Description",
"Store","DC","Date","Type","Promo Retail","Reg. Retail 50" "Units",
"Sales $", "Profit $"],
// $("#load_navGrid").html("Loading...").show();
colModel: [
{name:"cmName",index:"cmName",classes:"metric",width:130,resizable:true,
align:"left"},
{name:"displayLocation",index:"displayLocation",width:80,align: "left"},
{name:"displayName",index:"displayName",width:225,align:"left"},
{name:"item",index:"item",sorttype:"int",width:60,align:"left"},
{name:"itemDescription",index:"itemDescription",width:230,align:"left"},
{name:"store",index:"store",sorttype:"int",width: 70,align: "right"//,
//unformat : spaceFormatter
},
{name: "dc", index: "dc", sorttype: "int",width: 60,align: "right"//,
//unformat : spaceFormatter
},
{name:"date",index:"date",sorttype:"date",datefmt:"mm-dd-yy",width:80,
align: "left"},
{name: "type",index: "type",width: 45,align: "left"},
{name: "price",index: "price",width: 70,align: "left"},
{name: "regRetail",index: "regRetail",width: 70,align: "left"},
{name:"units",index:"units",sorttype:"int",width:45,align:"right",
unformat : spaceFormatter},
{name:"sales",index:"sales",sorttype:"int",width:45,align:"right",
unformat : spaceFormatter},
{name:"profit1",index:"profit1",sorttype:"int",width:40,align:"right",
unformat : spaceFormatter}
],
width: 982,
height: 137,
toolbar: [true, "top"],
viewrecords: true,
rowNum: 1500,
// gridview:true,
loadonce:true
});
Please suggest me how to improve performance of jqGrid
Use virtual scrolling (look at the demo, New in version 3.7 -> Virtual scrolling).
You question look like another question from trirand forum which I recently answered. To be sure I can repeate the information here.
In general for jqGrid is not a problem to display 1000 rows. The demo example which has 15 columns and 1000 rows will be displayed on my computer quickly enough. I have no IE7, but in IE8, IE9 beta, Chrome, Firefox, Opera and Safari (all in the last versions) the time to display the table is very quickly. In the example I use the modified jQuery UI, where .ui-widget :active { outline: none; } is removed. See here and here for more detailes.
So to be able to help you one need have possible full definition of your jqGrid inclusive the HTML code and test JSON data. You can capture the data with respect of Fiddler or Firebug. Probably you has some datatypes, don't use gridview:true option and use afterInsertRow method which make jqGrid working slower espetially for lagre pages. It can be also that you do many work inside of gridComplete or loadComplete event handler. So without having the code I can only guess. It can be also important which column you use for the sorting of the data and how you inserts the data in the grid (with data parameter, loadonce:true or using addRowData).
Another point of view is the usage of local paging. If you prefer to return all 1000 rows at once from the server it disturbs you not to use local paging of the 1000 rows of data. On the next example I demonstrate this. The problem is easy: all 1000 rows can not be displayed for the user at once. The user have to scroll the rows either in web browser or with respect fo jqGrid local paging. The advantage of the local paging is: only the data for one page will be placed in the table. All other data will be only hold in the sorted form internally. It can improve the performance and don't change almost anything from the users point of view.
More then that, having intelligent local filtering of data with respect of toolbar filtering or single field/advanced searching can help the user very much to analyse a lot of information from the 1000 rows which will be displayed him. Local filtering and local paging can be used very native together.