Connect by JBRH Open Connect

Virtualised rendering

Virtualised rendering draws only the rows currently visible, plus a small margin, and reuses that handful of elements as you scroll. It is how a grid stays responsive at thousands of rows. What it costs is everything that assumed the whole list was present: find-in-page, screen readers, selection across a scroll, and naive keyboard navigation.

Status
Reference What this means
Audience
both, developer
In the app
#/data
Last verified
Product version
6.3.2

What the browser is actually being spared#

Each element on a page carries layout, style resolution, event wiring and accessibility metadata. Those costs are individually tiny and they multiply: a grid of ten thousand rows across twenty columns is two hundred thousand cells, and the browser will attempt to lay all of them out before showing you the first one.

Virtualisation replaces that with a fixed budget. A spacer establishes the full scroll height so the scrollbar is honest, a window of rows is rendered inside it, and scrolling swaps the contents of those rows rather than creating more. The work per frame stops depending on how much data exists.

Fixed row height
The simple case: the position of row n is arithmetic, and scrolling to any row is exact
Variable row height
Positions have to be measured or estimated, and a wrong estimate makes the scrollbar shift under the reader's hand
Overscan
The margin of rows drawn beyond the viewport so that fast scrolling does not show blank space
Recycling
Reusing an existing row element for new data instead of creating one — the source of most virtualisation bugs, because stale state travels with the element

The four things that break#

  1. Find-in-page. The browser can only search what is in the document. A row that has not been drawn will not be found, and the reader has no way to know the difference between “not present” and “not drawn”. A grid that virtualises needs its own search, in the data.
  2. Assistive technology. A screen reader announces a table by its rows. If only twenty exist at a time, the row count, the position and the navigation all have to be declared explicitly rather than inferred.
  3. Selection across scrolling. Selecting a range and scrolling past the window means the earlier rows no longer exist as elements. Selection has to live in the data model, keyed by record, not in the DOM.
  4. Sorting and filtering in the view. Reordering only what is drawn produces a grid that is sorted differently in different places. The order belongs to the query.

Does Connect use virtualised rendering?#

Yes — the Data screen (#/data) is an Excel-like grid over 13 record sheets, and it is virtualised. Alongside that it carries sorting, filtering, grouping, frozen columns, resizing and reordering, saved views, inline editing, bulk actions, duplicate detection, import and CSV export.

Two design decisions matter more than the virtualisation itself. Every change made in the grid goes through the service that owns the record — the grid is not a second CRM sitting beside the first, and an edit here obeys the same rules an edit anywhere else obeys. And the ordering, filtering and counting happen in SQL rather than over a fetched slice, which is the lesson from the conversation list that counted 430 conversations by reading 400 of them.

The frontend it lives in is plain ES modules with no build step, so the virtualisation is code in the feature rather than a framework's behaviour — which makes the four failure modes above things to handle explicitly rather than things inherited.

Working with a virtualised grid#

  1. Use the grid's own search and filters rather than the browser's find.

    Result You are searching the data rather than the twenty rows that happen to be drawn.

  2. Filter first, then select. Bulk actions apply to the selection you have defined, not to what is visible.

    Result Scrolling does not silently change what a bulk action will touch.

  3. Save a view when a combination of filters, grouping and column order is one you return to.

    Result The arrangement is reproducible instead of rebuilt from memory.

  4. Export when you need the whole set outside the product.

    Result CSV export gives you every matching row rather than the drawn ones — and it neutralises formulas on the way out.

Questions#

Why does the browser's find not locate a row I know exists?

Because only the rows near your scroll position exist in the page at all. Everything else is described by a spacer that reserves the height. Use the grid's own search, which queries the data rather than the document — that is also what makes it able to find a row that would be on page forty.

If I select rows and scroll away, is the selection lost?

No. Selection is held against the records rather than against the drawn elements, which is what allows a bulk action to apply to a set larger than the screen. The practical habit is still to filter down to what you mean before selecting, so the set is one you can see the shape of.

Does virtualisation make the underlying queries faster?

No, and treating it as a performance fix is the common mistake. It bounds the browser's work only. The database side is bounded separately, by paging and filtering in SQL and by keeping the statement count flat with page size.