Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(table): table virtualization #10182

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Conversation

aborjinik
Copy link
Contributor

The ui5-table-virtualizer component is used inside the ui5-table to virtualize the table rows.It is responsible for rendering only the rows that are visible in the viewport and updating them on scroll. This allows large numbers of rows to exist, but maintain high performance by only paying the cost for those that are currently visible.

This component is experimental.

@aborjinik aborjinik force-pushed the virtualizer-table-new branch 3 times, most recently from 29849dc to b322a2a Compare November 15, 2024 14:17
@@ -210,6 +214,11 @@ class TableNavigation extends TableExtension {
this._gridWalker.setCurrent(eventOrigin);
}

this._table._getVirtualizer()?._onKeyDown(e);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe something for the future as an improvement. It would be nice to fire an event here instead, which would allow other components/extensions/features to possibly react to keydown events from TableNavigation.
Will also decouple TableNavigation from TableVirtualizer, which would be nice

This should be done in a follow up change/once we finalize the Virtualizer

@@ -284,6 +293,7 @@ class TableNavigation extends TableExtension {
if (this._table.loading) {
this._table._loadingElement.focus();
} else {
this._getNavigationItemsOfGrid();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this being called here and not used?

@@ -115,7 +115,11 @@ class TableNavigation extends TableExtension {
}

this._ignoreFocusIn = ignoreFocusIn;
element.focus();
if (element === this._table._beforeElement || element === this._table._afterElement) {
element.focus({ preventScroll: true });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personal preference, but we could omit the if statement here:

element.focus({
  preventScroll: element === this._table._beforeElement || element === this._table._afterElement
});


/**
* Fired when the virtualizer is changed by user interaction e.g. on scrolling.
* @param {first} number The 0-based index of the first children currently rendered
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be vice versa?

@param {number} first

Same goes for last


/**
* Fired when the virtualizer is changed by user interaction e.g. on scrolling.
*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing event parameters

}

this._updateRowsHeight();
if (this._tabBlockingState & TabBlocking.Released) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This _tabBlockingState is extremely confusing. It is defined as an Enum, but you use it for bit operations.
I do get the idea (this only evaluating to true, if the blockingState is Next|Previous when it was released/invalidated), but on first sight it is extremely confusing.

We can keep these flags here (I do like bit shenanigans), but enum is misleading here a bit, as the _tabBlockingState is also able to take the value 5 or 6

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe instead of _tabBlockingState being of type Enum, it is an explicit number representing bit flags instead (0b0000) and you instead of defining the Enum with integer values, you use binary instead?

enum TabBlocking {
  None = 0,
  Next = 1,
  Previous = 0b10,
  Released = 0b100
}

}

const scrollTop = this._scrollContainer.scrollTop;
const fixHeight = this._table.headerRow[0].offsetHeight;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only required if the header is sticky, right? So maybe this should be conditional


_updateRowsHeight() {
const rowsHeight = this.rowCount * this.rowHeight;
this._rowsContainer.style.minHeight = `${rowsHeight}px`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why minHeight and not height?

}

get _scrollContainer() {
return this._table!._tableElement;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this working for something like this?

<div style="height: 375px; overflow: auto">
  <ui5-table>
    <ui5-table-virtualizer row-height="51" row-count="1000" slot="features"></ui5-table-virtualizer>
  </ui5-table>
</div>

If that is not the case, we might need to explicitly document the restrictions

};

/**
* @class
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It breaks if overflowMode=Popin. Maybe a validation would be nice here, that either throws an error or "corrects" the value to Scroll
Should be documented as well

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants