In corporate or enterprise platforms, the representation of tabular data in single-page web apps is a common occurrence. There are challenges with the amount of data rows, the variety of data types, and number of simultaneous columns enterprise users wish to see.
In addition, the perceived performance of tabular data in a client-side web application can be affected by many factors. Ideally, the users would like to have all of the relevant data available locally (not requiring multiple round-trips to the web server) and still have lightning fast performance.
Our team develops single-page applications (SPA) for our customer. SPA is a web application that doesn’t reload at any point of time. Instead all necessary code is loaded at once or dynamically when is requested usually by a user action.
When developing a web page under AngularJS:
- data comes from a web service, database, etc.
- an HTML table is rendered from an array of entities using the ng-repeat directive,
- one-way binding to dynamically render an HTML table is used,
- rendering process takes time when you have hundreds of rows, tens of columns, or you format table cells,
- this will likely discourage the user because the perceived performance is poor.
Solution Options & Overview
One approach would be to use to pagination approach that divides the data into discrete pages. The performance is good however the user has to click to get next or previous page.
- render only visible data rows which fill the available space of the browser window,
- custom scrollbar next to table shows current relative position of the visible data vs the entire data set,
- scrollbar gradually fills-up with its background color when the user scrolls down the table,
- allows the user to have entire dataset at hand,
- intention is NEITHER to render the whole table NOR to display the common vertical scrollbar, only visible data rows,
- HTML table occupies a major portion of the browser window (appropriate # of rows),
- browser window size changes trigger table computation of visible area (similar to WinForms behavior).
HTML table with virtual scrolling
My goal was to quickly display only range of data and also allow the user to browse it at ease. The solution renders an HTML table by displaying appropriate number of rows to fit the browser window as if it were a Windows application. By hooking to the window resize event if the browser window size changes, the table height will be re-computed.
The table height is computed within the ng-style directive so the table fits the available browser screen space.
The table uses the ng-repeat directive and a custom range filter to display current range of data. To know how many rows to display in the table, the rendering process is intercepted by a custom directive and the height of first row is computed. The solution expects each row to have the same height. When the table height and rows height are known, it is easy to compute the number of to be displayed rows.
The table columns width depends on their content. When you scroll the table up or down, one row is removed and a new one is added to table. If the content changes, table column width may change which is an unexpected behavior. From this reason every column has a pre-defined width in the table header.
A custom scrollbar displayed to the right of table shows the current position in the whole array of data. The user can use the scrollbar to scroll up and down the table to see rows which are not currently visible. In contrary to the common scrollbar, the custom scrollbar gradually fills-up when the user scrolls down the table.
Consider the restrictions
The solution has some limitations though:
- If the content above or below the HTML table changes, the table height needs to be re-computed,
- the height of each row in the HTML table should be the same. When the first row is rendered, the solution finds out its height. Since we know the height of the first row and the HTML table, we can easily compute the number of visible rows. Also the row height should not change.
This solution renders HTML table fast regarding the amount of data because only data that can be visible NEEDS to be rendered. The next step to take is implementing the solution under Angular (technically Angular 2) to utilize its speed and performance.