TableExport
TableExport copied to clipboard
Error: Failed to execute 'setItem' on 'Storage': Setting the value of 'te-ec8b88f-xlsx' exceeded the quota.
I'm running an Angular 4 application and when I switch in and out (several times, like more than 10) into the component that uses the library, I get the following message and blocks the whole app execution.
Error: Failed to execute 'setItem' on 'Storage': Setting the value of 'te-ec8b88f-xlsx' exceeded the quota. at LocalStorage.setItem (tableexport.js:797) at TableExport.xlsx (tableexport.js:345) at tableexport.js:126
line 797: return this.store.setItem(key, value);
link to code
line 345: _store.getInstance().setItem(hashKey, dataObject, true);
link to code
line 126: context.setExportData(self.exporters[key].call(self, context));
link to code
@jorgeandresserrano - This was an error in object storage and hashCode that should be fixed in v5.0.0-rc.10
where I switched from LocalStorage
to SessionStorage
and drastically reduced the size of the objects in storage. I also just fixed master
so that it points to this latest version.
If the problem persists, try giving the <table>
elements an id
property. The hashKey
that I am using is computed based on the table id
attribute combined with the export type (e.g. xlsx
) and falls back to the internal _uuid
function to assure uniqueness which may be causing the problem for larger tables after multiple rerenders.
Lastly, if neither of those fix the issue then I may need to either create a utility to clear out unused export blobs from session storage or use an indexeddb.
@clarketm hi. Having similar problem with my use case... I have table generated in my react component with dynamic ID that can change even with data change in the table. Would it be possible to allow something like data-export-id to be used in your hash creating instead of id (if this attribute is set, use it, or fallback to id and your default fallbacks...). I need dynamic ID on the table to bind some non-react JS code on the table. But in worst case, I can switch to using class name as my unique referrer instead of ID, but using ID seems more logical and is faster.
@soukupl – check out the latest commit a2158d2. I am preparing this for v5.0.0-rc.11
.
The reference key value will default to the value of the id
property if defined, otherwise, it will be generated.
<table id="my-table" tableexport-key="my-table">
...
</table>
The attribute name can be customized via the following prototype property:
// Attribute applied to each table element
TableExport.prototype.tableKey = 'tableexport-key' // default
@clarketm seems to work for me now :) I also did tweak my code to better support your plugin. :) Anyway, my integration is now working, so big thank you :)
@soukupl – I am always open to suggestions for improvement if it aids in utility. If you don't mind me asking, what was your tweak?
@clarketm I change my code to work in a different way...
- I render the table and export button, but not initialize your lib
- If user clicks my export button -> 2a. I will add "working" overlay to block the UI 2b. I will initialize your code to prepare the table 2c. I will manually start CSV or XLS export via your API 2d. I will remove my "working" overlay to unblock the UI 2e. I will unload your code.
I have few hooks that can be injected so I can modify table before I initialize your code (didn't use it, but I will have to for my specific table). This way, I can control what I'm displaying and what I'm exporting in single table.
The think is, that my code is changing the table almost all the time as all data in the table are async and may even react to push notifications in one case. So your code needs to refresh it's prepared data and it was slow for big tables... I can change the table like 2 times in one second in extreme case... So this init/deinit on demand is actually faster.
exportTable__do(exportMode) {
console.log("[ElmTable] Export to: ", exportMode);
var exportHelper = TableExport(document.getElementById(this.state.tableHtmlId), {
formats: [exportMode],
exportButtons: false,
filename: "table-export"
});
var exportData = exportHelper.getExportData();
console.log(exportData);
var exportDataKey = Object.keys(exportData)[0];
exportData = exportData[exportDataKey][exportMode];
exportHelper.export2file(
exportData.data,
exportData.mimeType,
exportData.filename,
exportData.fileExtension
);
exportHelper.reset();
exportHelper.remove();
setTimeout(() => {
this.setState({ isLoading: false });
}, 250);
}
This is just the main part of the export code, but there are some other things going on async to this. The whole table is rendered from the object stored in react's state and the export is in fact executed when specific change to the state happens.
*) and yes, console.log is stripped in production build :D
sessionStorage.clear();
this.tableExport = new TableExport();