Last generated: 2026-07-20 06:21 UTC
Learn how to use every UI5 control in ABAP — the UI5 Demo Kit rebuilt with abap2UI5.
You know the drill from the UI5 Demo Kit: pick a
control, open its sample, copy the pattern. This repository brings that
experience to ABAP — the official demo kit samples of ten UI5 libraries
(sap.m, sap.f, sap.ui.core, sap.ui.layout, sap.ui.table,
sap.ui.unified, sap.uxap, sap.tnt, sap.ui.codeeditor,
sap.ui.integration), rebuilt 1:1 as ready-to-run abap2UI5 apps. Wondering
how to express a control in ABAP? Its sample is already here — or on its way.
- Install abap2UI5.
- Pull this repository with abapGit.
- Start
z2ui5_cl_smpc_app_overview— every sample in one searchable table: each row links the original UI5 sample and its ABAP rebuild, and one click starts the app right in your system.
No ABAP system at hand? Open the GitHub Pages demo — the framework and every sample run fully client-side in your browser.
This repository is step 2 of 3 — the control reference of the abap2UI5 sample family:
| Repository | What you learn | Where to start | |
|---|---|---|---|
| 1️⃣ | samples | the abap2UI5 basics — bindings, events, popups, navigation, complete apps | run Z2UI5_CL_SMP_APP_000 |
| 2️⃣ | samples-controls — 📍 you are here | how to use every UI5 control — the UI5 Demo Kit rebuilt with abap2UI5 | run z2ui5_cl_smpc_app_overview |
| 3️⃣ | samples-stack | how abap2UI5 plays with your stack — OData, RAP, WebSockets, the Fiori Launchpad and more | pick your technology in its package table |
Every port keeps the structure of its original, so the two read side by side:
the UI5 original (JS/XML) in ui5/, the ABAP rebuild in src/,
and api.md as the full index — one row per demo kit sample, with
links to both. The most effective way to learn a control: open its demo kit
sample and its ABAP class next to each other and compare line by line.
How this repository is built — the generation pipeline
This repository is generated and gated by an AI coding agent: from every official demo kit sample of the covered libraries whose control exists since UI5 1.71 and is not deprecated (legacy-free ready), it builds an abap2UI5 app — exposing the functional gaps between what UI5 offers and what abap2UI5 can already express, so they can be closed. Deprecated or newer controls are listed as out of scope. The pipeline:
- Read — clone OpenUI5 and scan every
demo kit sample of the covered libraries
(
src/<library>/test/<library path>/demokit/sample/<Name>/, second segment with dots as slashes, e.g.src/sap.tnt/test/sap/tnt/…). - Generate — rebuild each sample 1:1 as an abap2UI5 app (
z2ui5_if_app), filed undersrc/<category>/<library>(src/01/01= OpenUI5 ≤ 1.71,sap.m— see AGENTS §3); both levels are derived from the port'smeta/sidecar. - Store templates — keep the original UI5 JS/XML templates in
ui5/, one folder per sample — only ported samples are archived; each batch copies its samples over from the OpenUI5 checkout. - Report — regenerate the coverage tables and the in-system
overview app. In api.md,
—marks an in-scope sample not yet ported (the backlog) and✗an out-of-scope one (deprecated / newer than UI5 1.71).
Reviewed, curated samples graduate to the hand-maintained abap2UI5/samples repository.
Generation prompt (UI5 sample → abap2UI5 app)
You are porting one official UI5 demo kit sample to abap2UI5.
Input: the sample's original files (Component.js, *.view.xml, controller,
manifest.json) from the OpenUI5 checkout.
Output: one ABAP class z2ui5_cl_smpc_app_<n> implementing z2ui5_if_app, that
rebuilds the sample's UI and behaviour 1:1.
Rules:
- Build the view with the generic builder z2ui5_cl_ai_xml, translating the
sample's XML 1:1 (open = descend into a container, leaf = childless
control/stay, shut = ascend). Attributes are added with
a( n = `key` v = `value` ) chained right after the control's open/leaf;
a targets that control, and v is any string expression (literal, a
client->_bind/_event result, a |...| string template). factory( )
returns an empty root: open the mvc:View and declare its xmlns namespaces
yourself. Blank line between controls whose verb differs (open<->leaf,
before shut); none between same-verb controls, none right after a shut,
none between a control and its attrs; the whole view ends in a single ).
An aggregation carries the same namespace as its XML tag (its parent
control's): <m:content> under a Page is open( n = `content` ns = `m` ),
a default-namespace <columns> inside an sap.ui.table.Table is open( `columns` ).
Braces { } inside a |...| template are ALWAYS escaped \{ \} - an unescaped {
is read as a binding by the XMLView parser and crashes view creation.
Booleans: literal v = `true`/`false`, or v = z2ui5_cl_ai_xml=>as_bool( flag )
when fed from an ABAP boolean variable.
- BEFORE declaring any sample feature inexpressible, check CAPABILITIES.md -
the map of what abap2UI5 can express, each entry backed by a proving port.
Never improvise around a feature it marks expressible.
- Structure z2ui5_if_app~main as a dispatcher:
me->client = client.
IF client->check_on_init( ).
model_init( ).
view_display( ).
ELSEIF client->check_on_event( ).
on_event( ).
ENDIF.
Add model_init / on_event only when the app actually has data / events.
z2ui5_if_app~main is always the FIRST method in the implementation; the
remaining methods follow in the order they are called from main, EXCEPT
model_init which always goes LAST (after every other method, and declared
last in the DEFINITION too) - its large mock-data VALUE #( ) block must not
interrupt the reading flow of the dispatcher/view/event methods.
- Always the simplest possible notation: omit parameters that equal the
default - get_event_arg( ) not get_event_arg( 1 ) (index only for 2+).
- Move the sample's JSON model data into ABAP (VALUE #( ... )) and bind it
with client->_bind (two-way; the former _bind_edit is obsolete - always use
_bind). Absent JSON properties must not serialize as empty strings: `""`
crashes enum-typed properties and overrides property defaults where the
original's undefined picked the default - fill the UI5 default explicitly
or split the aggregation into per-shape templates.
- abap2UI5 serves ONE default model - there are no named models. A named-model
binding ({ui>/rowMode}, {img>/x}) is folded into the default model: drop the
prefix and bind the field directly (client->_bind( rowmode )); structural-diff
matches on the last path segment. A typed/complex binding is kept as a raw
binding-info string, braces escaped: |\{ path: 'Q', type:
'sap.ui.model.type.Integer' \}| (same for Date/Currency parts and sorter) -
it passes through to XMLView.create unmangled. See the port-a-sample guide (.claude/skills/port-a-sample/SKILL.md)
"Idiom cheat-sheet".
- Frontend actions: a control method LISTED in CONTROL_METHODS
(FrontendAction.js) carries explicit arg kinds and silently drops every
argument beyond them - verify the kinds before a parametrized call. An
UNLISTED public method also runs unless it matches the deny regex
(destroy/bind/attach/setModel/...); a denylisted or argument-dropping
need is a declared deviation plus a pr/ request, never a LIVE_TEST hope.
popover_display imports xml + by_id (the XML parameter is `xml`, not
`val`).
- Map controller event handlers to check_on_event( ) branches. To pass a value
into an event, use the `$`-prefixed form in t_arg (a model column as
`${COL}`, the event object as `$event.oSource.sId` / `${$source>/text}`) and
read it back with get_event_arg( ) - a bare `{COL}` (the attribute
property-binding form) is NOT resolved there. Transport real event/source
values this way instead of faking a static placeholder.
- The sample's CONTROL must exist since UI5 1.71 and not be deprecated
(out-of-scope samples are never ported). Members newer than 1.71 are KEPT
1:1 when the original uses them - declare each in the sidecar as a
POST_171 deviation naming the member (the property gate checks this).
- Must pass abaplint for ABAP_STANDARD, ABAP_CLOUD and ABAP_702 (downport).
- The class carries NO ABAP Doc header. Write the port's sidecar
meta/z2ui5_cl_smpc_app_<n>.json instead (sample, entity, file, batch, audit,
status, deviations) - see AGENTS.md section 5 and the port-a-sample guide; validate with
node scripts/validate-meta.mjs.
- Any runtime asset URLs the sample uses (test-resources / resources images)
also point at the OpenUI5 host (sdk.openui5.org), never SAPUI5.
- Leave the abapGit <DESCRIPT> as the scaffolder's `<library> - <sample name>`
default (e.g. `sap.f - GridListBoxContainerGrouping`); only improve the
trailing text to a human phrase when you know one. Don't agonize over
entity-vs-library (see AGENTS.md section 5 and the port-a-sample guide).
- Follow all ABAP conventions in AGENTS.md.
Ports are filed by the sample's UI5 library — src/01 (sap.m), src/02
(sap.ui.*), src/03 (sap.uxap), src/04 (sap.f), src/05 (sap.tnt)
— one flat ABAP package per library; see AGENTS §3 for the folder table. The
generation/review batch a port came from is recorded in its
meta/<class>.json, not in the tree. The browser demo is built from
web/ into docs/; see web/README.md.
| File | What it is |
|---|---|
AGENTS.md |
The complete generation rulebook (conventions, skeleton, gates) |
CAPABILITIES.md |
What abap2UI5 can express — each entry backed by a proving port or a source-verified trace |
TRAINING.md |
The improvement loop: batches, quality ladder, reference repositories |
STATUS.md |
Generated point-in-time state + the open findings backlog |
STATUS-history.md |
The chronological journal (batches, probes, audits) |
api.md |
One row per demo kit sample: ported, backlog or out of scope |
meta/ |
One sidecar per port — status, checked, typed deviations |
pr/ |
Forwardable improvement requests for the abap2UI5 framework, distilled from porting gaps |
| ai-mcp | MCP server for AI coding agents — capability queries, view validation, deploy, headless run + screenshot on this repo's infrastructure (separate repository) |
| abap2UI5-linter | The view gates as standalone CLI, library and GitHub Action — extracted from this repo and now used BY it (scripts/view-gates.mjs) |
Every app is ABAP Cloud ready and downportable to 7.02. In detail, every app:
- uses only controls available since UI5 1.71 (16 Jan 2020), none of
them deprecated (legacy-free ready). Individual members newer than 1.71
are kept where the original sample uses them — declared per port
(
POST_171), so those apps need a correspondingly recent UI5; - runs on SAPUI5 and OpenUI5, including the legacy-free runtime;
- runs on ABAP Cloud and ABAP Standard, and downports to 7.02.
CI enforces this on every change:
| Build | What it does |
|---|---|
ABAP_STANDARD |
abaplint ./abaplint.jsonc (syntax v750) |
ABAP_CLOUD |
abaplint .github/abaplint/abap_cloud.jsonc (syntax Cloud) |
ABAP_702 |
npm run downport → abaplint .github/abaplint/abap_702.jsonc |
checks |
pattern-lint (distilled lessons), structural-diff --strict (port vs original view incl. binding values, undeclared deviations fail), view-gates (abap2UI5-linter: UI5 metadata, builder structure, headless XMLView.create per port), data-fidelity (seeded values vs the archived mocks), validate-meta + overview/coverage sync |
Every port also carries a machine-readable sidecar meta/<class>.json
(sample, status, declared deviations) — the source of truth the overview app,
the coverage and the structural diff read from.
Coverage per UI5 library — the share of official demo kit samples that already have an abap2UI5 port.
Overall 411 / 628 in-scope demo kit samples ported (65.4 %).
In scope: samples whose control exists since UI5 1.71 and is not deprecated (legacy-free ready).
Out of scope: 113 of 741 samples — 21 on deprecated controls, 52 on controls newer than 1.71, 37 that are not app views (UI5 test infrastructure, Component routing, view-templating demos — see ui5/scope-nonapp.json), 3 demo apps without an owning control.
Plus 5 ported samples outside that scope — maintainer-decided exceptions (ui5/scope-exceptions.json, listed in STATUS.md); they are not counted as coverage of the in-scope backlog.
Control metadata from OpenUI5 1.152.0.
| Module | Samples | In scope | Ported | Coverage | |
|---|---|---|---|---|---|
sap.tnt |
17 | 17 | 17 | 100.0 % | ██████████ |
sap.ui.codeeditor |
2 | 2 | 2 | 100.0 % | ██████████ |
sap.ui.core |
63 | 20 | 20 | 100.0 % | ██████████ |
sap.ui.integration |
4 | 4 | 4 | 100.0 % | ██████████ |
sap.ui.layout |
61 | 61 | 61 | 100.0 % | ██████████ |
sap.ui.table |
21 | 21 | 21 | 100.0 % | ██████████ |
sap.ui.unified |
21 | 21 | 21 | 100.0 % | ██████████ |
sap.uxap |
45 | 45 | 31 | 68.9 % | ███████░░░ |
sap.m |
461 | 403 | 217 | 53.8 % | █████░░░░░ |
sap.f |
46 | 34 | 17 | 50.0 % | █████░░░░░ |
| Total | 741 | 628 | 411 | 65.4 % | ███████░░░ |
For the full control-level view — one row per sample (Module · Control ·
Since · Deprecated · Sample · ABAP), every link pointing at OpenUI5 — see
api.md, or the in-system overview app z2ui5_cl_smpc_app_overview,
where the Sample column links the OpenUI5 source (its ↗ opens the live
sample) and the abap2UI5 column links the generated class (its ↗ starts the
app in the system).
The coverage summary and api.md are generated by the generate_result
workflow (scripts/generate-coverage.mjs), and the overview app by
scripts/generate-overview.mjs, both from the latest OpenUI5 demo kit
samples — do not edit them by hand.
For bug reports or feature requests, please open an issue in the abap2UI5 repository.