diff --git a/plugins/ui5/README.md b/plugins/ui5/README.md index 720130d..e8ea7fb 100644 --- a/plugins/ui5/README.md +++ b/plugins/ui5/README.md @@ -51,6 +51,19 @@ Guidelines and debugging workflow for OPA5 integration tests: - **Page object organization** - Placement of actions and assertions across views - **App teardown** - Cleanup patterns in OPA5 journey tests +#### ui5-best-practices-tables + +Authoritative development guidelines for all UI5 table controls (SAPUI5 1.136+ LTS): + +- **Control selection matrix** - When to use `sap.m.Table`, `sap.ui.table.Table`, `TreeTable`, `SmartTable`, or `sap.ui.mdc.Table` +- **Core rules and prohibitions** - Mandatory patterns and common mistakes to avoid +- **Common errors** - Symptom/cause/fix table for the most frequent table bugs +- **Container structures** - Valid and invalid layout containers for tables +- **Per-control API guidance** - Binding syntax, key properties, minimal examples, and events for each table type +- **Drag & drop** - Correct `DragDropInfo` and `DragInfo`/`DropInfo` configuration +- **Personalization** - `sap.m.p13n.Engine` integration +- **Cell templates & alignment** - Type-based alignment and model type namespace rules + --- ## Installation diff --git a/plugins/ui5/skills/ui5-best-practices-tables/SKILL.md b/plugins/ui5/skills/ui5-best-practices-tables/SKILL.md new file mode 100644 index 0000000..0f12da3 --- /dev/null +++ b/plugins/ui5/skills/ui5-best-practices-tables/SKILL.md @@ -0,0 +1,144 @@ +--- +name: ui5-best-practices-tables +description: | + UI5 table best practices and authoritative development guidelines. Use when the user asks to "create a table", "add a table", "which table should I use", "implement sap.m.Table", "implement sap.ui.table", "GridTable", "ResponsiveTable", "TreeTable", "SmartTable", "MDC table", "sap.ui.mdc.Table", "sap.ui.comp.smarttable", "table not showing data", "table binding", "table selection", "drag and drop table", "table personalization", "copy paste table", "table export", "table sticky header", "table growing", "table pop-in", "table performance", "table accessibility", "table items binding", or is writing any UI5 freestyle application that includes a table control. Covers: control selection matrix, mandatory rules, common error patterns, and per-control API guidance for sap.m.Table, sap.ui.table.Table, sap.ui.table.TreeTable, sap.ui.comp.smarttable.SmartTable, and sap.ui.mdc.Table. + + Keywords: sap.m.Table, sap.ui.table, GridTable, ResponsiveTable, TreeTable, SmartTable, sap.ui.mdc.Table, table binding, rows aggregation, items aggregation, rowMode, growing, sticky, personalization, drag and drop, DragDropInfo, p13n.Engine, OData V4, OData V2, cell templates, ariaLabelledBy +--- + +# UI5 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`](references/sap-m-table.md) | +| Working on or planning a `sap.ui.table.Table` (GridTable) | [`references/grid-table.md`](references/grid-table.md) | +| Working on or planning a `sap.ui.table.TreeTable` | [`references/tree-table.md`](references/tree-table.md) | +| Working on or planning a `sap.ui.comp.smarttable.SmartTable` | [`references/smart-table.md`](references/smart-table.md) | +| Working on or planning a `sap.ui.mdc.Table` | [`references/mdc-table.md`](references/mdc-table.md) | +| Adding drag-and-drop to any table | [`references/drag-and-drop.md`](references/drag-and-drop.md) | +| Adding column personalization | [`references/personalization.md`](references/personalization.md) | +| Choosing cell templates, alignment, or data type binding | [`references/cell-templates.md`](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](#selection-matrix) before writing any code. +- Use the `rows` aggregation for `sap.ui.table.*` and `items` for `sap.m.Table`. Never swap them. +- Use `sap.m.p13n.Engine` for personalization. Never build custom personalization dialogs. +- Set `ariaLabelledBy` on 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.Text` for display, `sap.m.ObjectNumber` for numbers, `sap.m.Link` for navigation. +- Request `$count=true` from the back end for `sap.ui.table.*` when a total count is required. +- Use the `rowMode` aggregation (not the deprecated `visibleRowCountMode` property) for `sap.ui.table.*` (UI5 1.119+). + +### Prohibitions + +- Do not use global variables. Use `sap.ui.define` AMD modules or ES6 imports. +- Do not enable text wrapping in `sap.ui.table.*` cells — it breaks virtualization. +- Do not assume `sap.ui.export.Spreadsheet` is available. Detect the library before use. +- Do not use `sap.ui.table.Table` for mobile-first scenarios. Use `sap.m.Table`. +- Do not use `sap.m.Table` for datasets with 1000+ rows that require virtualization. +- Do not place multiple interactive elements in one `sap.ui.table.Table` cell. +- Do not return enum objects from formatters. Return string literals or primitive values. +- Do not use formatters for `ColumnListItem` `highlight`. 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, or `sap.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.Table` cells. +- Multiple interactive elements in one GridTable cell. +- Mixing OData V2 `SmartTable` with V4 services. +- Deep nesting in cell templates. +- Fixed `threshold` without load testing. +- Unconditional `$count=true` (request count only when needed). + +### Accessibility checklist + +- Set `ariaLabelledBy` on 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. diff --git a/plugins/ui5/skills/ui5-best-practices-tables/references/cell-templates.md b/plugins/ui5/skills/ui5-best-practices-tables/references/cell-templates.md new file mode 100644 index 0000000..95c570f --- /dev/null +++ b/plugins/ui5/skills/ui5-best-practices-tables/references/cell-templates.md @@ -0,0 +1,44 @@ +# Cell Templates & Alignment + +## Alignment by data type + +| Data type | Alignment | Property | +|---|---|---| +| Text | Left | default | +| Numbers | Right | `hAlign="End"` | +| Dates | Right | `hAlign="End"` | +| Boolean | Left | default | +| Links | Left | default | + +Set `hAlign` on the `Column` control, not on the cell template. + +## Cell template selection + +| Content type | Template control | +|---|---| +| Plain text | `sap.m.Text` | +| Formatted number / amount | `sap.m.ObjectNumber` | +| Navigation | `sap.m.Link` | +| Status | `sap.m.ObjectStatus` | +| Icon | `sap.ui.core.Icon` | + +## Model type binding + +NEVER mix type namespaces. Always match the type namespace to the model: + +```xml + + + + + + + + +``` + +| Model | Type namespace | +|---|---| +| JSON | `sap.ui.model.type.*` | +| OData V2 | `sap.ui.model.odata.type.*` | +| OData V4 | `sap.ui.model.odata.v4.type.*` | diff --git a/plugins/ui5/skills/ui5-best-practices-tables/references/drag-and-drop.md b/plugins/ui5/skills/ui5-best-practices-tables/references/drag-and-drop.md new file mode 100644 index 0000000..83fcdd8 --- /dev/null +++ b/plugins/ui5/skills/ui5-best-practices-tables/references/drag-and-drop.md @@ -0,0 +1,50 @@ +# Drag & Drop + +Configure drag-and-drop on the **table**, not on individual items or cells. + +**❌ Wrong — DnD on the item:** +```xml + + + + + + + + +
+``` + +**✅ Correct — reordering within the same table using `DragInfo` + `DropInfo` with matching `groupName`:** +```xml + + + ... + + + + + +
+``` + +**✅ Alternative — using `DragDropInfo` (no `groupName` needed for same-table reorder):** +```xml + + + + +
+``` + +## Key rules + +- For reordering within the same table: use `DragDropInfo`, or set a matching `groupName` on both `DragInfo` and `DropInfo`. +- For drag between different tables: use matching `groupName` values on both tables. +- Update the bound model in the `drop` handler to reflect the new order. diff --git a/plugins/ui5/skills/ui5-best-practices-tables/references/grid-table.md b/plugins/ui5/skills/ui5-best-practices-tables/references/grid-table.md new file mode 100644 index 0000000..93e299f --- /dev/null +++ b/plugins/ui5/skills/ui5-best-practices-tables/references/grid-table.md @@ -0,0 +1,79 @@ +# sap.ui.table.Table (GridTable) + +API: https://ui5.sap.com/1.136.0/api/sap.ui.table.Table + +## Minimal complete example + +```xml + + + + + + + <ToolbarSpacer/> + <Button icon="sap-icon:action-settings" press=".onPersonalize"/> + </OverflowToolbar> + </table:extension> + <table:rowMode> + <table:rowmodes:Fixed rowCount="10"/> + </table:rowMode> + <table:columns> + <table:Column> + <Label text="Name"/> + <table:template><Text text="{name}" wrapping="false"/></table:template> + </table:Column> + <table:Column hAlign="End"> + <Label text="Price"/> + <table:template><ObjectNumber number="{price}" unit="{currency}"/></table:template> + </table:Column> + </table:columns> + </table:Table> + </Page> +</mvc:View> +``` + +## Key properties + +| Property | Type | Default | Since | Notes | +|---|---|---|---|---| +| `selectionBehavior` | SelectionBehavior | RowSelector | 1.0 | `Row`, `RowSelector`, `RowOnly`. | +| `columnHeaderVisible` | boolean | true | 1.0 | Show/hide column headers. | +| `showNoData` | boolean | true | 1.0 | Show "No data" text. | +| `noData` | string / Control | — | 1.0 | Custom no-data content. | +| `showOverlay` | boolean | false | 1.21 | Block interaction with overlay. | +| `threshold` | int | 100 | 1.0 | Prefetch buffer for virtualization. | + +## rowMode aggregation (UI5 1.119+) + +Use the `rowMode` aggregation instead of the deprecated `visibleRowCountMode` property. + +```xml +<table:rowMode> + <table:rowmodes:Fixed rowCount="10"/> +</table:rowMode> +``` + +Available row modes: `Fixed`, `Auto`, `Interactive`. + +## Selection behavior + +- `Row`: selection changed anywhere in the row, including the selector column. +- `RowSelector`: selection changed only via the selector column; row clicks do not select. +- `RowOnly`: selection changed only via row clicks; the selector column is hidden. + +Do not call the table's selection API when a `SelectionPlugin` is attached. Use the plugin API instead. + +## No-data customization + +```xml +<table:Table> + <table:noData> + <IllustratedMessage illustrationType="NoData" title="No Products"> + <Button text="Add Product" press=".onAddProduct"/> + </IllustratedMessage> + </table:noData> +</table:Table> +``` diff --git a/plugins/ui5/skills/ui5-best-practices-tables/references/mdc-table.md b/plugins/ui5/skills/ui5-best-practices-tables/references/mdc-table.md new file mode 100644 index 0000000..50cd113 --- /dev/null +++ b/plugins/ui5/skills/ui5-best-practices-tables/references/mdc-table.md @@ -0,0 +1,48 @@ +# sap.ui.mdc.Table + +API: https://ui5.sap.com/1.136.0/api/sap.ui.mdc.Table + +## Delegate pattern + +`sap.ui.mdc.Table` uses a delegate for metadata and data operations. Implement both `fetchProperties` and `updateBindingInfo`. + +Minimal delegate: +```javascript +sap.ui.define(["sap/ui/mdc/odata/v4/TableDelegate"], function(TableDelegate) { + const MyDelegate = Object.assign({}, TableDelegate); + + MyDelegate.fetchProperties = function(oTable) { + return Promise.resolve([ + { + key: "name", label: "Name", + dataType: "sap.ui.model.type.String", + sortable: true, filterable: true + }, + { + key: "price", label: "Price", + dataType: "sap.ui.model.type.Float", + sortable: true, filterable: true + } + ]); + }; + + return MyDelegate; +}); +``` + +## MDC table usage + +```xml +<mdc:Table id="mdcTable" header="Products" + delegate="{name: 'my/app/delegate/TableDelegate', payload: {entitySet: 'Products'}}" + p13nMode="Column,Sort,Filter" autoBindOnInit="true"> + <mdc:columns> + <mdc:Column header="Name" propertyKey="name"> + <Text text="{name}"/> + </mdc:Column> + <mdc:Column header="Price" propertyKey="price"> + <ObjectNumber number="{price}"/> + </mdc:Column> + </mdc:columns> +</mdc:Table> +``` diff --git a/plugins/ui5/skills/ui5-best-practices-tables/references/personalization.md b/plugins/ui5/skills/ui5-best-practices-tables/references/personalization.md new file mode 100644 index 0000000..b0d11c8 --- /dev/null +++ b/plugins/ui5/skills/ui5-best-practices-tables/references/personalization.md @@ -0,0 +1,13 @@ +# Personalization + +Use `sap.m.p13n.Engine` for all personalization. Do not build custom personalization dialogs. + +```javascript +Engine.getInstance().show(oTable, ["Columns", "Sort", "Filter"], { + contentWidth: "30rem", + contentHeight: "35rem", + source: oButton +}); +``` + +Register the table with the Engine before calling `show`. diff --git a/plugins/ui5/skills/ui5-best-practices-tables/references/sap-m-table.md b/plugins/ui5/skills/ui5-best-practices-tables/references/sap-m-table.md new file mode 100644 index 0000000..b432e10 --- /dev/null +++ b/plugins/ui5/skills/ui5-best-practices-tables/references/sap-m-table.md @@ -0,0 +1,199 @@ +# sap.m.Table (ResponsiveTable) + +API: https://ui5.sap.com/1.136.0/api/sap.m.Table + +## Items binding syntax + +The `items` attribute on `<Table>` defines the binding configuration. The `<items>` element defines the template. Both are required. + +**✅ Correct — simple binding:** +```xml +<Table items="{/products}"> + <items> + <ColumnListItem> + <cells> + <Text text="{name}"/> + </cells> + </ColumnListItem> + </items> +</Table> +``` + +**✅ Correct — complex binding with sorter/filter:** +```xml +<Table items="{ + path: '/products', + sorter: { path: 'name' } +}"> + <items> + <ColumnListItem> + <cells><Text text="{name}"/></cells> + </ColumnListItem> + </items> +</Table> +``` + +**❌ Wrong — path on `<items>` element (will not work):** +```xml +<Table> + <items path="/products"> + <ColumnListItem>...</ColumnListItem> + </items> +</Table> +``` + +## Minimal complete example + +```xml +<mvc:View xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" controllerName="my.app.controller.Main"> + <Page title="Products"> + <Table id="responsiveTable" items="{/products}" growing="true" + growingThreshold="20" ariaLabelledBy="tableTitle" + sticky="ColumnHeaders,HeaderToolbar"> + <headerToolbar> + <OverflowToolbar> + <Title id="tableTitle" text="Products" level="H2"/> + <ToolbarSpacer/> + <Button icon="sap-icon:action-settings" press=".onPersonalize"/> + <Button icon="sap-icon:excel-attachment" press=".onExport"/> + </OverflowToolbar> + </headerToolbar> + <columns> + <Column> + <header><Text text="Name"/></header> + </Column> + <Column demandPopin="true" minScreenWidth="Tablet"> + <header><Text text="Category"/></header> + </Column> + <Column hAlign="End"> + <header><Text text="Price"/></header> + </Column> + </columns> + <items> + <ColumnListItem> + <cells> + <Text text="{name}"/> + <Text text="{category}"/> + <ObjectNumber number="{price}" unit="{currency}"/> + </cells> + </ColumnListItem> + </items> + </Table> + </Page> +</mvc:View> +``` + +## Column header + +Always use the `header` aggregation. + +**❌ Wrong:** +```xml +<Column><Text text="Name"/></Column> +``` + +**✅ Correct:** +```xml +<Column> + <header><Text text="Name"/></header> +</Column> +``` + +## Sticky headers (UI5 1.58+) + +```xml +<Table sticky="ColumnHeaders,HeaderToolbar" items="{/products}"> +``` + +Valid `sticky` values: `ColumnHeaders`, `HeaderToolbar`, `InfoToolbar`. Combine with commas. + +## Key properties + +| Property | Type | Default | Since | Notes | +|---|---|---|---|---| +| `growing` | boolean | false | 1.16.0 | Enable load-more. | +| `growingThreshold` | int | 20 | 1.16.0 | Items per load. | +| `growingScrollToLoad` | boolean | false | 1.16.0 | Load on scroll vs. button. | +| `sticky` | Sticky[] | — | 1.58 | Sticky column/header/info toolbar. | +| `multiSelectMode` | MultiSelectMode | Default | 1.93 | `Default` or `ClearAll`. | +| `rememberSelections` | boolean | true | 1.16.6 | Set to `false` with `$$sharedRequests`. | +| `autoPopinMode` | boolean | false | 1.0 | Auto-hide columns by importance. | +| `contextualWidth` | ScreenSize | undefined | 1.60 | Container-based responsive behavior. | +| `hiddenInPopin` | string[] | [] | 1.77 | Hide columns completely by ID. | +| `popinLayout` | PopinLayout | Block | 1.52 | Block / GridLarge / GridSmall. | +| `fixedLayout` | FixedLayout | true | 1.0 | Use `Strict` for precise widths. | +| `keyboardMode` | KeyboardMode | Navigation | 1.38 | `Navigation` or `Edit`. | + +## OData V4 selection + +Set `rememberSelections="false"` when using `$$sharedRequests` or `$$clearSelectionOnFilter`. + +## Responsive behavior patterns + +Container-based width: +```xml +<Table contextualWidth="Desktop" items="{/products}"> +``` + +Hide columns completely (reference by column ID): +```xml +<Table hiddenInPopin="categoryCol,statusCol" items="{/products}"> + <columns> + <Column id="categoryCol" demandPopin="true" minScreenWidth="Tablet"/> + </columns> +</Table> +``` + +Auto pop-in by importance: +```xml +<Table autoPopinMode="true" items="{/products}"> + <columns> + <Column importance="High"><header><Text text="Name"/></header></Column> + <Column importance="Medium"><header><Text text="Category"/></header></Column> + <Column importance="Low"><header><Text text="Status"/></header></Column> + </columns> +</Table> +``` + +## ColumnListItem highlight + +Do not use a formatter for `highlight`. Use direct binding or `ObjectStatus`. + +Valid `highlight` values: `None`, `Success`, `Warning`, `Error`, `Information`. + +## Events + +| Event | Since | Parameters | Use | +|---|---|---|---| +| `paste` | 1.60 | `data: string[][]` | Paste tabular data. | +| `popinChanged` | 1.77 | `hasPopin`, `visibleInPopin[]`, `hiddenInPopin[]` | Track responsive changes. | +| `updateStarted` / `updateFinished` | 1.16.3 | `reason`, `actual`, `total` | Busy indicators. | +| `beforeOpenContextMenu` | 1.54 | `listItem`, `column` | Context menu. | + +## Grouping with sap.ui.model.Sorter + +**✅ Correct:** +```javascript +_createCategorySorter: function() { + return new Sorter("category", false, function(oContext) { + var sCategory = oContext.getProperty("category"); + return { key: sCategory, text: sCategory }; + }); +}, +this.byId("productsTable").getBinding("items").sort(this._createCategorySorter()); +``` + +**❌ Wrong — do not pass the group header factory as the grouper function:** +```javascript +new Sorter("category", false, this.getGroupHeader.bind(this)) +``` + +**Group header factory (separate):** +```javascript +getGroupHeader: function(oGroup) { + return new GroupHeaderListItem({ + title: oGroup.text, + count: "(" + oGroup.count + ")" + }); +} +``` diff --git a/plugins/ui5/skills/ui5-best-practices-tables/references/smart-table.md b/plugins/ui5/skills/ui5-best-practices-tables/references/smart-table.md new file mode 100644 index 0000000..266fdc5 --- /dev/null +++ b/plugins/ui5/skills/ui5-best-practices-tables/references/smart-table.md @@ -0,0 +1,58 @@ +# sap.ui.comp.smarttable.SmartTable + +API: https://ui5.sap.com/1.136.0/api/sap.ui.comp.smarttable.SmartTable + +## Key annotations + +| Annotation | Purpose | +|---|---| +| `@UI.LineItem` | Define columns and column order. | +| `@UI.Hidden` | Exclude a field from the table. | +| `@UI.Importance` | Responsive priority: `High`, `Medium`, `Low`, `None`. | +| `@Common.Label` | Column header text. | +| `@Measures.ISOCurrency` | Currency formatting. | + +## Annotation pattern + +```xml +<Annotations Target="MyService.Product"> + <Annotation Term="UI.LineItem"> + <Collection> + <Record Type="UI.DataField"> + <PropertyValue Property="Value" Path="ProductID"/> + <Annotation Term="UI.Importance" EnumMember="UI.ImportanceType/High"/> + </Record> + <Record Type="UI.DataField"> + <PropertyValue Property="Value" Path="Name"/> + <Annotation Term="UI.Importance" EnumMember="UI.ImportanceType/High"/> + </Record> + <Record Type="UI.DataField"> + <PropertyValue Property="Value" Path="Price"/> + <Annotation Term="UI.Importance" EnumMember="UI.ImportanceType/Medium"/> + </Record> + </Collection> + </Annotation> +</Annotations> +``` + +## SmartTable configuration + +```xml +<smartTable:SmartTable id="smartTable" entitySet="Products" + tableType="ResponsiveTable" + useTablePersonalisation="true" + useVariantManagement="true" + useExportToExcel="true" + header="Products" + showRowCount="true" + enableAutoBinding="true" + ignoredFields="InternalID" + requestAtLeastFields="Currency"/> +``` + +## Troubleshooting + +- Column does not appear: add a `DataField` record to `UI.LineItem`. +- Wrong column header: add or correct `Common.Label`. +- Column hidden: adjust `UI.Importance` to `Medium` or `High`. +- Missing currency formatting: add `Measures.ISOCurrency`. diff --git a/plugins/ui5/skills/ui5-best-practices-tables/references/tree-table.md b/plugins/ui5/skills/ui5-best-practices-tables/references/tree-table.md new file mode 100644 index 0000000..42ae8c9 --- /dev/null +++ b/plugins/ui5/skills/ui5-best-practices-tables/references/tree-table.md @@ -0,0 +1,54 @@ +# sap.ui.table.TreeTable + +API: https://ui5.sap.com/1.136.0/api/sap.ui.table.TreeTable + +## Key properties + +| Property | Description | +|---|---| +| `useGroupMode` | Group headers vs. tree icons. | +| `groupHeaderProperty` | Property for group header text. | + +## Hierarchical binding + +JSON model: +```javascript +rows="{path: '/categories', parameters: {arrayNames: ['children']}}" +``` + +OData V2: +```xml +<table:TreeTable rows="{ + path: '/Nodes', + parameters: { + countMode: 'Inline', + treeAnnotationProperties: { + hierarchyLevelFor: 'HierarchyLevel', + hierarchyNodeFor: 'NodeID', + hierarchyParentNodeFor: 'ParentNodeID', + hierarchyDrillStateFor: 'DrillState' + } + } +}"> +``` + +Root level configuration: +```javascript +oTable.bindRows({ + path: "/Employees", + parameters: { + rootLevel: 1, + navigation: { Employees: "Manager" } + } +}); +``` + +## Programmatic control + +Use `expandToLevel`, `collapseAll`, `expand`, and `collapse` to manage hierarchy state. + +## Restrictions + +- No mobile equivalent. +- The first column cannot be moved or have columns moved before it (preserves tree structure). +- Fixed bottom rows are supported via `rowMode` but are typically used for summary rows only.