When copying sevreal thousand rows into handsontable from excel it throws
Uncaught Error: Security brake: Too much TRs.
Please define height for your table, which will enforce scrollbars.
I set the height in the constructor
var options = {
height : 340,
minSpareRows : 1,
minSpareCols : 1,
colHeaders : false,
contextMenu : true,
columnSorting: true,
...
}
Same error - Is there any way to overcome this ?
Second, How can i catch this error ?
I just ran a quick test with handsontable, using 14 columns, I was able to load about 1200 rows. This is indicative of a cell number of about 16 000.
You can try lazy or delayed loading of data by adding a callback that is triggered on paste by handsontable.
Otherwise you can use the callback on paste to check the length of the data on the clipboard first and displaying an error if it is too big.
var clipText = window.clipboardData.getData('Text');
This allows you to access text from the clipboard in javascript.
Regarding your second question of displaying a scroller:
$("#myHandsontable").bind('paste', function () {
$('#updateProgress').show();
});
Then in the constructor use the after change event:
$("#myHandsontable").handsontable({
...
afterChange: function(changes, source) {
if (source == "paste") {
$('#UpdateProgress').hide();
}
}
});
Although you should try the latest version of handsontable, they really made a huge improvement in the time that it takes to paste data in the table.
I just had this issue, it is a bit misleading due to the wording of the error,
Error: Security brake: Too much TRs. Please define height for your
table, which will enforce scrollbars.
The error suggests that defining a height will force scroll bars, but in fact, I fixed it by defining a height that was small enough so scrollbars were forced on the table.
Hope my version makes more sense...
Everything seems to work fine then.
Related
I am going to do live data streaming on ag-grid datatable, so I used DeltaRowData for gridOptions and added getRowNodeId method as well which return unique value 'id'.
After all, I got a live update result on my grid table within some period I set, but some rows are duplicated so I can notice total count is a bit increased each time it loads updated data. The question title is warning message from browser console, I got bunch of these messages with different id number. Actually it is supposed not to do this from below docs. This is supposed to detect dups and smartly added new ones if not exist. Ofc, there are several ways to get refreshed data live, but I chose this one, since it says it helps to persist grid info like selected rows, current position of scroll on the grid etc. I am using vanilla js, not going to use any frameworks.
How do I make live data updated periodically without changing any current grid stuff? There is no error on the code, so do not try to speak about any bug. Maybe I am wrong with current implementation, Anyway, I want to know the idea or hear any implementation experience on this.
let gridOptions = {
....
deltaRowDataMode: true,
getRowNodeId = (data) => {
return data.id; // return the property you want set as the id.
}
}
fetch(loadUrl).then((res) => {
return res.json()
}).then((data) => {
gridOptions.api.setRowData(data);
})
...
If you get:
duplicated node warning
it means your getRowNodeId() has 1 value for 2 different rows.
here is part from source:
if (this.allNodesMap[node.id]) {
console.warn("ag-grid: duplicate node id '" + node.id + "' detected from getRowNodeId callback, this could cause issues in your grid.");
}
so try to check your data again.
if u 100% sure there is an error not related with your data - cut oof the private data, create a plinkr/stackblitz examples to reproduce your issue and then it would be simpler to check and help you.
I have below code
$.fn.dataTableExt.aoFeatures.push({
"fnInit": function (oSettings) {
oSettings.oScroll.sY = 5;
return { "oSettings": oSettings } ;
},
"cFeature": "T"
});
$.extend($.fn.dataTable.defaults, {
//"scrollY": 5,
"dom":"T"
});
I can see scrollY changed in function but no effect in datatable, How can overwrite the default setting using this function, since i have to put condition ono tableid,
otherwise I could have done below way which is working
$.extend($.fn.dataTable.defaults, {
"scrollY": 5,
});
I believe I am missing something on return statement which will override the things
fiddle reference
You code is not working for a few reasons. First, you are using an outdated API. $.fn.dataTableExt.aoFeatures.push is the old API used with $(...).dataTable(). By using $(...).DataTable() (note the capital "D") as you did in your fiddle, you are choosing to use the new API. (Read about converting code using the old API to use the new API here.) Using the current API is a great choice, but you then need to use $.fn.dataTable.ext.feature.push to set up your feature.
This works:
$.fn.dataTable.ext.feature.push({
"fnInit": function (settings) {
settings.oScroll.sY = 25;
},
"cFeature": "T"
});
However, the dom feature is intended to indicate the order of elements in the table. Using it to set style like scrollY is OK, but not exactly what they had in mind. The point being that if you are going to specify dom at all, you have to specify all the elements you want. In particular, you have to specify t for table or else the DataTable will not attach itself to the table at all. So you need to set up your table with something like this to trigger your scrollY "feature":
$(document).ready(function() {
var table = $('#example').DataTable({
"dom":"Tlftip"
});
Note that the order matters. The "T" has to come before the other elements that are affected by the changes made in the feature. "dom":"lftipT" will not have the desired effect.
I have a not too big grid (30x20) with numbers in cells. I have to display all, calculate them in different ways (by columns, rows, some cells, etc.) and write values to some cells. This data is also written and read from db table fields. Everything is working, excluding simple (theoretically) mask tools.
In time of e.g. writing data to the field in the table I try to start mask and close it on finish. I used such a “masks” very often but only in this situation I have a problem and can’t solve it.
I prepare this mask the following way:
msk = new Ext.LoadMask(Ext.getBody(), { msg: "data loading ..." });
msk.show();
[writing data loops]
msk.hide();
msk.destroy();
I also tried to use grid obiect in place of Ext.getBody(), but without result.
I found also that the program behaves in a special way – loops which I use to write data to the table field are "omitted" by this mask, and it looks like loops are working in the background (asynchronously).
Would you be so kind as to suggest something?
No, no, no, sorry guys but my description isn’t very precise. It isn’t problem of loading or writing data to the database. Let’s say stores are in the memory but my problem is to calculate something and write into the grid. Just to see this values on the screen. Let me use my example once again:
msk = new Ext.LoadMask(Ext.getBody(), { msg: "data loading ..." });
msk.show();
Ext.each(dataX.getRange(), function (X) {
Ext.each(dataY.getRange(), function (Y) {
…
X.set('aaa', 10);
…
}
msk.hide();
msk.destroy();
And in such a situation this mask isn’t visible or is too fast to see it.
In the mean time I find (I think) a good description of my problem but still can’t find a solution for me. When I use e.g. alert() function I see this mask, when I use delay anyway, mask is too fast. Explanation is the following:
The reason for that is quite simple - JS is single threaded. If you modify DOM (for example by turning mask on) the actual change is made immediately after current execution path is finished. Because you turn mask on in beginning of some time-consuming task, browser waits with DOM changes until it finishes. Because you turn mask off at the end of method, it might not show at all. Solution is simple - invoke store rebuild after some delay.*
I have no idea how is your code looks in general but this is some tip that you could actually use.
First of all loading operations are asynchronously so you need to make that mask show and then somehow destroy when data are loaded.
First of all check if in your store configuration you have autoLoad: false
If yes then we can make next step:
Since Extjs is strongly about MVC design pattern you should have your controller somewhere in your project.
I suppose you are loading your data on afterrender or on button click event so we can make this:
In function for example loadImportantData
loadImportantData: function(){
var controller = this;
var store = controller.getStore('YourStore'); //or Ext.getStore('YourStore'); depends on your configuration in controller
var myMask = new Ext.LoadMask(Ext.getBody(), {msg:"Please wait..."});
myMask.show();
store.load({
callback: function (records, operation, success) {
//this callback is fired when your store load all data.
//then hide mask.
myMask.hide();
}
});
}
When data is loaded your mask will disappear.
If you have a reference to the grid, you can simply call grid.setLoading(true) to display a loading mask over the grid at any time.
I have a grid.Panel inside of a viewport that is binded to a store. Once the grid (or store) is loaded, I would like to look at a value in the first row (or any row), and if it's false, hide a column in the grid. I've tried many different events, but here's an example in my controller:
Ext.define('HelperBatchForm.controller.BatchController', {
extend: 'Ext.app.Controller',
stores: [
'Batches'
],
models: [
'Batch'
],
views: [
'batch.BatchGrid',
'batch.BatchEdit'
],
init: function () {
this.control({
'batchgrid': {
itemdblclick: this.editBatch
,viewready: this.onGridLoad
}
});
},
onGridLoad: function(grid){
stop;
},
"Stop" throws an error and opens the debugger in my IE browser. On the browser itself I can see the grid, and the rows, fully rendered. In the debugger, I can look at grid.store.data.items[0] and see the first row. So it seems that everything is well, and I should be able to put a condition in the function based on that data which hides the grid. But that doesn't work - here is where things start to get weird.
If I replace "stop;" with "debugger;", and reload, this time we get the visual studio debugger. But now, in the IE screen, I can only see the grid headers, and none of the data. And grid.store.data.items is an empty array. The instant I resume, I see the full grid.
But that's not all. If my function is:
onGridLoad: function (grid) {
alert('onGridLoad');
debugger;
},
Now, with the visual studio debugger loaded, I can see the full grid and data in IE. And grid.store.data.items[0] gives me the first row. If I replace "debugger" with my conditional code, it works! In other words, I have code that doesn't work, but suddenly starts working if I throw an alert() before it.
To summarize, the code below will hide the column:
onGridLoad: function (grid) {
alert('onGridLoad');
if (grid.store.findExact('is_rcm', false) >= 0) {
grid.columns[6].hide();
}
},
But if the alert is commented out, it will not hide the column.
Any ideas or explanations to why this might be would be greatly appreciated.
My guess the issue here is related to async loading of the store. You are probably seeing a race condition of a split second between the view is ready but the store is not yet populated. Just like in quantum physics the observation of the event is changing its outcome :)
My suggestion is to put a load listener on the store instead and inject your processing at that point.
I think that #dbrin is correct in assuming the data in the store is not yet loaded. But doing the processing on store load might also be problematic, when store load time is very fast, and the view is not yet ready. The following should work when the data is ready either after or before the view:
viewready: function(grid){
grid.getView().on({
refresh: {
fn: function(){
if (grid.store.findExact('is_rcm', false) >= 0) {
grid.columns[6].hide();
}
},
single: true
}
});
}
And here is a fiddle, where you can set the store load delay to test for different load times.
this question has already been answered multiple times. but here I want to site that if the code provided in the documentation can't be achieved without additional codes, why it has been given there in first place. Its simply misleading. The code given in the documentation achieves paging, but while sorting, the grid data simply disappears.
Correct me if I am wrong.
jQuery("#gridid").jqGrid({
...
datatype: 'json', // can be xml
loadComplete : function () {
jQuery("#gridid").jqGrid('setGridParam',{datatype:'local'});
},
onPaging : function(which_button) {
jQuery("#gridid").jqGrid('setGridParam',{datatype:'json'});
},
...
});
You don't posted the exact reference to the documentation where you get the code. I found it here.
jqGrid is open source product which you get for free. It's practical, but you should understand, that in the case the product and its documentation could not be perfect. The part of code which you referenced could work probably in some very old version of jqGrid, but it's wrong code in the current version of jqGrid. The sense of implementing "Client side sorting, but server side paging" is very suspected at all. My old answer about the subject you would find here. I would rewrite some part of the answer now, but in general the code tested with old versions could be not full compatible with the new version of jqGrid.
I can say there is no place where intentional misleading has happened. They are giving the pluging for free though it is a very huge plugin. And the work done by people like Oleg is making it more perfect. For you question, the code related to "client side sorting and server side paging" here is the code that can solve your problems. And this was taken with the help of some old answer given by Oleg.
This is my version of code,
loadComplete: function(data) {
var $this = $(this);
if ($this.jqGrid('getGridParam', 'datatype') === 'json') {
// because one use repeatitems: false option and uses no
// jsonmap in the colModel the setting of data parameter
// is very easy. We can set data parameter to data.rows:
$this.jqGrid('setGridParam', {
datatype: 'local',
data: data.userdata,
pageServer: data.page,
recordsServer: data.records,
lastpageServer: data.total
});
// because we changed the value of the data parameter
// we need update internal _index parameter:
this.refreshIndex();
if ($this.jqGrid('getGridParam', 'sortname') !== '') {
// we need reload grid only if we use sortname parameter,
// but the server return unsorted data
$this.triggerHandler('reloadGrid');
}
} else {
$this.jqGrid('setGridParam', {
page: $this.jqGrid('getGridParam', 'pageServer'),
records: $this.jqGrid('getGridParam', 'recordsServer'),
lastpage: $this.jqGrid('getGridParam', 'lastpageServer')
});
this.updatepager(false, true);}
}
onPaging:function(){
/*this code is to fix the issue when we click on next page with some data in filter tool bar
* along with this in grid definition( in filterToolbar ) we have to return true in "beforeClear "event
* */
var data = $(this).jqGrid("getGridParam", "postData");
data._search = false;
data.filters=null;
data.page=$(this).jqGrid("getGridParam","page");
/* comment this line if you disable filter toolbar*/
$(this)[0].clearToolbar();
//Here making _search alone false will not solve problem, we have to make search also false. like in below.
$(this).jqGrid('setGridParam', { search: false, postData:data });
var data = $(this).jqGrid("getGridParam", "postData");
/*this is to fix the issue when we go to last page(say there are only 3 records and page size is 5) and click
* on sorting the grid fetches previously loaded data (may be from its buffer) and displays 5 records
* where in i am expecting only 3 records to be sorted out.along with this there should be a modification in source code.
*/
$(this).jqGrid("clearGridData");
/* this is to make the grid to fetch data from server on page click*/
$(this).setGridParam({datatype: 'json'}).triggerHandler("reloadGrid");
}
For the modification that you have to do in source code is , see this answer..