About ui5-best-practices-tables
A guidance skill for generating, reviewing, and troubleshooting tables in freestyle SAPUI5 applications. It selects table types and provides implementation, accessibility, and performance rules for SAPUI5 1.136+.
Key features
- 01Table type selection guidance
- 02Rules for bindings and cell templates
- 03Personalization and drag-and-drop references
- 04Accessibility and performance checks
- 05Common table error troubleshooting
Use cases
- 01Choosing a table for a dataset and device context
- 02Reviewing SAPUI5 table code before implementation
- 03Diagnosing binding, scrolling, or export issues
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ ui5/ plugins-coding-agents --skill ui5-best-practices-tablesAfter installing, type/ui5-best-practices-tablesin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
references/cell-templates.mddrag-and-drop.mdgrid-table.mdmdc-table.mdpersonalization.mdsap-m-table.mdsmart-table.mdtree-table.mdDetails
From the project READMEUI5 Table Best Practices
Apply these guidelines whenever generating, reviewing, or troubleshooting UI5 table code in freestyle applications.
UI5 version baseline: SAPUI5 1.136+ LTS. All features mentioned are available from this version unless noted.
When to load each reference
| Trigger | Load |
|---|---|
Working on or planning a sap.m.Table (ResponsiveTable) | references/sap-m-table.md |
Working on or planning a sap.ui.table.Table (GridTable) | references/grid-table.md |
Working on or planning a sap.ui.table.TreeTable | references/tree-table.md |
Working on or planning a sap.ui.comp.smarttable.SmartTable | references/smart-table.md |
Working on or planning a sap.ui.mdc.Table | references/mdc-table.md |
| Adding drag-and-drop to any table | references/drag-and-drop.md |
| Adding column personalization | references/personalization.md |
| Choosing cell templates, alignment, or data type binding | references/cell-templates.md |
Load before producing any output. Do not work from memory.
Core Rules
Mandatory
- Choose the table type using the Selection Matrix before writing any code.
- Use the
rowsaggregation forsap.ui.table.*anditemsforsap.m.Table. Never swap them. - Use
sap.m.p13n.Enginefor personalization. Never build custom personalization dialogs. - Set
ariaLabelledByon every table, referencing the table title control. - Align cell content by data type: numbers and dates right (
hAlign="End"), text and links left. - Use appropriate cell templates:
sap.m.Textfor display,sap.m.ObjectNumberfor numbers,sap.m.Linkfor navigation. - Request
$count=truefrom the back end forsap.ui.table.*when a total count is required. - Use the
rowModeaggregation (not the deprecatedvisibleRowCountModeproperty) forsap.ui.table.*(UI5 1.119+).
Prohibitions
- Do not use global variables. Use
sap.ui.defineAMD modules or ES6 imports. - Do not enable text wrapping in
sap.ui.table.*cells — it breaks virtualization. - Do not assume
sap.ui.export.Spreadsheetis available. Detect the library before use. - Do not use
sap.ui.table.Tablefor mobile-first scenarios. Usesap.m.Table. - Do not use
sap.m.Tablefor datasets with 1000+ rows that require virtualization. - Do not place multiple interactive elements in one
sap.ui.table.Tablecell. - Do not return enum objects from formatters. Return string literals or primitive values.
- Do not use formatters for
ColumnListItemhighlight. Use direct data binding. - Do not access models without checking availability — causes "Cannot read properties of undefined".
- Do not mix type namespaces: never use
sap.ui.model.odata.type.*with a JSON model, orsap.ui.model.type.*with OData.
OData V4 policy
Prefer SAP Fiori elements building blocks over freestyle tables for OData V4. Use sap.ui.mdc.Table only when Fiori elements is out of scope.
Selection Matrix
| Table type | Use when | Do not use when |
|---|---|---|
sap.m.Table | Mobile/responsive, pop-in behavior, JSON models, fewer than 100 rows | 1000+ rows, virtualization required, desktop-only, cell selection needed |
sap.ui.table.Table | Desktop, 1000+ rows, virtualization, fixed columns, dense data | Mobile-first, pop-in required, text wrapping, small datasets |
sap.ui.table.TreeTable | Hierarchical data, expand/collapse, parent-child relationships | Flat data, mobile-first, grouping (not hierarchy) |
SmartTable | OData V2, annotations, automatic columns, smart filtering | JSON-only, precise control required, OData V4 |
sap.ui.mdc.Table | OData V4 freestyle (when Fiori elements is ruled out), delegate pattern | JSON-only, simple apps, OData V2 |
Dataset size guide
| Rows | Recommended table | Strategy |
|---|---|---|
| < 100 | sap.m.Table | Simple binding, growing optional |
| 100–1000 | sap.ui.table.Table | Virtualization, threshold=100 |
| 1000+ | sap.ui.table.Table | Virtualization, threshold=100–500, $count=true when needed |
Common Errors
| Symptom | Cause | Fix |
|---|---|---|
| No data displayed | Incorrect binding path or missing model | Verify bindRows/bindItems path and model attachment. |
Rows not scrolling (sap.ui.table.*) | Count not requested | Set $count=true for OData when a total count is required. |
Selection not working (sap.ui.table.*) | Plugin conflict | Do not call the table selection API when a selection plugin is applied; use the plugin API instead. |
| Text wrapping issues | Wrapping enabled in sap.ui.table.* | Use fixed-height content or switch to sap.m.Table. |
| Copy/paste not working | Plugin not attached or wrong namespace | Attach the correct plugin (see Drag & Drop section). |
| Personalization not persisting | Engine not configured | Verify sap.m.p13n.Engine registration. |
CopyProvider error | extractData not defined | Implement extractData on the plugin. |
| Table not visible | Invalid container structure | Use a valid container (see Container Structures). |
| OData types on JSON model | Wrong type namespace | Match the type namespace to the model: sap.ui.model.type.* for JSON, sap.ui.model.odata.type.* for OData V2, sap.ui.model.odata.v4.type.* for OData V4. |
| Excel export fails silently | Library not loaded or invalid extractData | Detect the library, return a 2D array from extractData, ensure dataSource binding. |
| "No Data Available" | Model not set before binding | Set the model in Component.init() before router initialization. |
Container Structures
Valid
| Structure | Use case |
|---|---|
View > Page > content > Table | Standard page |
View > Page > content > Panel > Table | Grouped content |
View > Page > content > IconTabBar > items > IconTabFilter > Table | Tabs |
View > SplitApp > detailPages > Page > Table | Master-detail |
View > Dialog > content > Table | Modal |
View > Table | Standalone |
Invalid (and why)
| Structure | Issue |
|---|---|
Page > content > VBox > Table | VBox needs explicit height — table becomes invisible |
Page > VBox > Table | VBox not in content — table not rendered |
Page > content > FlexBox > Table | Sizing conflict — table collapses |
Page > content > ScrollContainer > Table | Double scrolling — virtualization breaks |
Performance & Accessibility
Anti-patterns to avoid
- Handcrafted personalization dialogs (use
sap.m.p13n.Engine). - Text wrapping in
sap.ui.table.Tablecells. - Multiple interactive elements in one GridTable cell.
- Mixing OData V2
SmartTablewith V4 services. - Deep nesting in cell templates.
- Fixed
thresholdwithout load testing. - Unconditional
$count=true(request count only when needed).
Accessibility checklist
- Set
ariaLabelledByon every table, referencing the visible title. - Use
sap.m.Text(not raw text nodes) as cell templates. - For
sap.ui.table.Table: test keyboard navigation (Tab, arrow keys, Space/Enter for selection). - Verify that the personalization dialog is keyboard-operable.
- Test with a screen reader (NVDA/JAWS on Windows, VoiceOver on macOS) before shipping.