Show HN: Tabulator – Easy-to-use JavaScript library for interactive tables
tabulator.info
tabulator.info
The front end requests to the backend each chart on the current dashboad, then the backend, depending of the type of chart, gets the data from the database and passes it to the front who renders it, it could be a pie chart, a bar chart, a table, etc.
We hade 2 or 3 different types of table charts, al using different js based solutions, one of them using bootstrap, i don't remeber the others.
The javascript solutions had responsiveness issues, when you changed the size of the window, or used something that is not Chrome, column headers messed everything up.
One day i decided to end that and added a new type of chart, it expected one table resultset from the db, and once in the front it rendered a traditional <table> with it's content.
We have no more problems with table charts. It works in every browser and every screen resolution.
It was possible to fix the current js tables of course, but is it realy necessary? We have been using tables since forever, and they are just to correct way to display table data on the web.
Thats it, it just works.
- With <div>, you have complete control over the positioning of the cells. With <table>, you delegate the layout to the browser engine. - <table> has lots of semantic meaning, which makes it slower to render than a <div>, because the browser engine needs to make a sense of it. - There are differences in how <table>s are rendered in various browsers. This is especially a problem with old browsers such as IE6. - It is trickier to implement things like floating headers, virtual scrolling with <table>
Still, Handsontable uses <table> because you can overcome these problems if you're motivated enough. The biggest benefit is that <table> gives you enhanced semantics, which are good for Accessibility, SEO or any other form of code processing.
Complex interactive tables need a great number of elements to make them run and these wont conform to the standards of using a table (you cant just put a div inside a tbody element) but that is exactly what you would need to to to get a table with a virtual DOM to work correctly.
There are a lot of different styling tweaks that would need to be overriden for each element, some of which arnt consistent across each browser.
Also people have a tendency to put styles on the generic table tab to style tables across the site. if Tabulator was to then be used on the page, it could have any number of unknown CSS properties set on it, so would essentially have to look at overriding all possible style properties.
where as no one generically styles divs or spans and they come with very little built in styling making them the ideal choice for a library that wants to keeps its functionality isolated from the rest of the site
I have to ask: is this really slower overall? I didn't try to make an exact 1:1 comparison, but in my experience, all JS-powered table libraries I've seen start choking around a couple hundred elements. With HTML tables + minimal styling, I can dump 10k+ rows with no performance penalty.
But when you start dealing with large volumes of data they quickly become the only option.
Even a plain html table with say 10 columns will crash out /massively slow down a browser if you load in 100,000 rows of data.
Browsers simply aren't able to process that may elements being added to the DOM.
In the case of Tabulator you can handle many thousands of rows because it only adds the rows you can see to the DOM, removing/adding them as you scroll.
So yes this means there is more processing when you scroll but at the same time you aren't trying to move 100,000 od DOM elements at once which reduces the load on the browser when loading/scrolling.
Depending on the complexity of what you are dealing with there becomes a point where the trade off in processing/memory usage makes it worthwile
I suspect that may be the primary reason, not JS. When you start juggling details that impact a cell, that in turn impacts all the rest of the table, so you can add up with an additive impact based on the number of cells. <divs> still have that, but actually fall under the well-optimized engine for rendering, well, divs (and other straightforward elements that only impact other elements via positioning, not by things like colspan and rowspan)
But this is speculation on my part. I can say that while I appreciate the semantic definition of table and use the tag appropriately in my own work, I never look forward to it because it's always more work than doing so with divs. There is a reason everyone was happy to leave table-based layout behind and it wasn't (just) a desire for semantic purity.
It is not neccessarily a bottleneck, as long as your datagrid library uses the browser's ability to render the table. But if you want a custom look and feel, such as overlapping cells, irregular shaped cells, animated cells, it's far better to do it based on <div>s instead of fighting the browser engine.
Performance is solid, it's easy to work with for ~90% of the times I use it and there are other ways to handle that last 10%.
I probably wouldn't have used datatables on greenfield but the legacy (in every sense) project I inherited already used it so I went with it anyway.
This is because the <table> element introduces a lot of design constraints.
There is a lot of inhernt styling that would have to be overridden if a table element was to be used. it could also mess with the standard behaviour of other table elements that have been generically styled.
Importantly when you start building interactive complex tables there are 100's of different types of elements needed to make the table function correctly that a standard HTML element simple isn't designed to handle, event making the header and the body scroll separately requirements more elements that a standard table can handle and it would invalid HTML to use the tags inside the table that would be needed to achieve it.
Especially when you move into the world of the virtual DOM a standard table element simply wont cut it
With the inclusion of aria tags there are no accessibility issues as screen readers treat them just as any other tables.
The virtual DOM, while very impressive, isn't necessary as well. Really depends on what problem you are solving there and what level of support you need for browsers. What problem are you solving? Many entries? Minimal cell mutation control?
For large data sets it makes the table work regardless of the number of rows
Lets say we are working with 10,000 rows
Yes loading that many elements into the DOM is slow and your approach would stop it blocking, however what it dosnt do is stop the sheer number of elements from overloading the DOM.
Most browsers simply cant handle that many elements in the DOM, if you try and scroll a div containing that may elements at best it will be sluggish and at worst it will simply crash the browser. on devices without much memory it is very likely that the whole DOM will freeze up and make the site unusable.
By adding and deleting the elements as they become visible/hidden it keeps the number of elements in the DOM to a minimum, while improving load time and adding only a bit of extra processing to the scroll event, which modern browsers can handle with ease. giving all round the best solution
I did this myself when writing a chat client's infinite history scrollback. Chat messages that aren't on the screen still have a pure-data "event" representation of them loaded, but their DOM representation (virtual or otherwise) is entirely discarded. Rather than the physical DOM nodes for chat-message divs having fixed positions such that they're able to disappear without affecting their peers' layout, I instead just have the chat messages stacked as regular block elements under reflow, with two fixed-size "scroll pad" divs just above and below the viewport "consuming" and "releasing" the vertical height that had been taken up by message divs as they're added and removed. You can have millions of rows "loaded" (in the sense of parsed data sitting in JS memory) for instant access, with not much browser memory usage at all.
Though, even that memory usage was too much (this chat client is supposed to run beside memory-intensive apps like games), so as well, in my setup, nodes that are far enough off the screen can have their parsed "event" representation discarded, and replaced with a single URL representing the serialized "history chunk" that those events came from. When the scroll distance comes close to them, the chunks are reloaded by re-requesting and re-parsing the chunk (which, helpfully, is usually still in the browser cache.)
We've since rewritten Dynatable to use vanilla JS and are in the process of renaming it to simply Dynatable instead of jQuery Dynatable.
Your audience is developers!
Edit: if I switch to desktop view I see a table.
I would suggest having an absolute minimal code + rendering on the front page somewhere. It tells me so much about your library than anything else could!
Yes the version for mobile is much less revealing im afraid, it was tricky to fit everything on the screen so i scaled back the homepage to something simpler.
Actually the documentation and example links are on the first paragraph of the site, just above the table, but i must have removed that whole section from the mobile view to make things fit in better. I will have a look into that now.
I ended up using https://www.ag-grid.com/ which started charging for features and appears to making good money. Have you considered going this route?
Long story short, for Angular there are similar widgets that also happen to be more popular. I didn't end up using them, so can't say for sure, but I imagine they fit more nicely with the framework they were made for.
Also, dunno if anything changed, but six months ago Tabulator could use some fine tuning in regard to UX with pagination: if the table is scrolled to the right, on every filtering or pagination operation the position is reset to zero (but not on the table headers, notably). There's also no support for more interesting filtering like number ranges, so I'd need to whip up widgets for that myself.
And, for some reason, the lib sent two data requests every time filters were changed.
Thanks for your feedback.
A lot has changed in the last 6 months, Tabulator now has its own react component, and the filter issues have been resolved.
There are also examples of how to build range filters in the example section.
If you have any particular areas of concern feel free to raise an issue on GitHub and they will be resolved.
As for tighter integration with frameworks, in the next release Tabulator will have a reactive data mode, that will allow it to change as data is changed in the column and data arrays, making it simpler that ever to work with the same design paradigm as modern frameworks
Also, thanks for explaining the implications of the MIT licence simply in the licence area - it's not something that those who are wet behind the ears always find easy.
What size of dataset (rows, columns) is Tabulator able to handle well?
For huge datasets, what options are available to partially display, paginate, or progressively load data?
Tabulator has a wide variety of options for handling large data sets. because it uses a virtual DOM you can effectively load as many rows as you like into the table, with the limit being defined by the amount of memory on the browsing machine and loading time to pull in the data.
With the virtual DOM enabled Tabulator will then only render the rows that are visible to the user, creating and destroying them in real time as the user scrolls through the table
To reduce loading time you can also:
Paginate data (both of local data and from an ajax source: http://tabulator.info/docs/4.1/page
Progressively load via ajax, both on scroll and timed: http://tabulator.info/docs/4.1/data#ajax-progressive
and also manually handle data retrieval yourself and use the replaceData function to swap out data sets as needed
I did a huge deep dive on HTML/Javascript table libraries when I started working on Polar - which is a document management platform for PDF and cached HTML content (https://getpolarized.io/)
Right now we're using React-Table (https://react-table.js.org/)
I didn't actually see Tabulator when I did the full comparison and this seems to be right up there with Tabulator.
Table support is hugely important for us. We have to render the list of PDFs and documents you're managing, sort them, and also not necessarily have to render them all on the same page, so having pagination is insanely important.
There's a few things react-table doesn't do a very good job on including key bindings so I'm going to have to take a look at this library too.
By removing the need for 3rd party dependencies it helps reduce the overall size of the package, made it easier to manage the source of the system, made it easier for developers to import and dramatically increased the performance of the table, Tabulator used to be built on jQuery but that was a beast of a library and eventually became a bottle neck harming performance more than it aided development.
Removing the need for dependencies was also a great learning experience to implement a variety of systems that you would usually go straight to another library for.
When there is something bespoke in one of the extensible modules there are the occasional use of library's, such as the xlsx downloader or the sparkline formatter. but i only use these in optional components and keep the core dependency free :)
Our custom solution is basically just a set of conventions for implementing html tables using a JS rendering library. We also wrote a set of single-purpose modules that can be applied to table-rendering views to provide specific features.
It also comes with a number of themes to help match other UI frameworks. See the themeing examples here: http://tabulator.info/examples/4.1#theming
As well as built in themes it comes with extensive documentation on the CSS classes as well as overrideable SASS variables for all themes to make customising as easy as possible, more information can be found in the styling documentation: http://tabulator.info/docs/4.1/style
each theme is contained in its own CSS file, you simply include the CSS file for the theme of your choice.
Configuring themes for your table is covered extensively in the documentation along with examples of each theme in use: http://tabulator.info/docs/4.1/theme
What was your overall high level approach, and which technologies did choose to use and avoid? Were some frameworks easier than others to integrate with, or have their unique challenges?
I would like to re-implement my old jQuery pie menus so they support various frameworks like Tabulator does, so I would really benefit from your thoughts and experiences, and any suggestions you have for following in your footsteps.
on the whole the key is to stick to vanilla JS and avoid trying to use to forcible a design paradigm that could conflict with other frameworks.
Removing dependencies on other libraries was key to making it interoperable.
Everything in Tabulator is built to be extensible so where an incompatibility exists it is easy to build a solution for a particular framework.
Tabulator still has one hangup in the way it works, in that it dosnt use reactive data (changing the array you passed into the table, does not automatically update the table, unlike react and view, you have to bind watchers at the moment) but this will be coming in the next release. at which point they should all work harmoniously
The biggest challenge is to ensure that things are drawn correctly at the correct time. Because Tabulator uses a virtual DOM it makes it a since to redraw parts of the table when needed
Any suggestions for interesting parts of the code I should snoop around? ;)
Tabulator has zero dependencies for its core functionality
If you have the time, writing a virtual DOM can be an excellent lesson in the intricacies of DOM manipulation, learning exactly what order to make calls in to optimize the number of times the DOM is updated and reduce the load on the system.
Though if you are not trying to write a lot of data to the screen they are not worth doing to be fair.
Tabulator needs one because if you try and load 10,000 rows of a table into the DOM at the same time it will freeze up as most browsers cant handle that load, but for simpler UI elements it may not be worth the added complexity.
In the documentation for tabulator there is an "Architecture Concepts" section that has a number of pages that provide a bit of detail about how Tabulator works.
The virtual DOM details can be found here: http://tabulator.info/docs/4.1/virtual-dom
and some basic lifecycle info can be found here: http://tabulator.info/docs/4.1/lifecycle
Also, thank you for the React compatibility and component, as well as the permissive license!
If that helps, console says it failed to load the following (but gave no reason):
>https://cdn.rawgit.com/google/code-prettify/master/loader/ru...
>https://cdn.rawgit.com/google/code-prettify/master/loader/la...
Maybe it's some cross-site loading being blocked, I dunno.
My only issue now is struggling with CSS to make it look nice :p
I would update my website(it already has a table sorting feature), but losing columns in favor of beauty isnt acceptable.
You can either choose to hide columns that do not fit, or collapse them into a list.
There are extensive options for configuring which columns react in what order and how things are displayed
Checkout the responsive layout documentation for more info: http://tabulator.info/docs/4.1/layout#responsive
This is really nice, very small for such a comprehensive library.
Jealous a bit, that library like this cannot work within React Native env.
I end up using React-native-web for everything that I can, and then, double-implement functions for web vs native, where parity cannot be achieved.
I use react native wrappers at work and embed webviews that allow components like these to be used.
That being said, having a react-native variant for this is on the long term road map
Especially because I cannot find a way to display Latex/MathML in React Native, without a webview.
AG-Grid focus's on being a fully functional spreadsheet where as tabulator goes more down the route of interactive table.
Tabulator has a publicly visible development roadmap so you can see roughly when new features are going to come online.
There is a new release every month or so, so if there is a feature you feel you need you can create an issue on GitHub to get it added to the roadmap.
Most importantly, Tabulator is FREE even for commercial use!
I am VERY excited to start trying to use this instead.