Status: normative, version 1. Machine-readable form:
portable-v1.json (shape:
../schema/portable-profile.schema.json).
Coverage data: portable-coverage.md. Method and
caveats of the census the list is drawn from: section 10.
The key words MUST, MUST NOT, SHOULD, SHOULD NOT and MAY are to be read as in RFC 2119 (../spec/README.md).
The core protocol (../spec/core.md) moves views as opaque
strings: a frontend that implements it can display something for every
VIEW_SLOTS display, but only the UI5 frontend understands every view an
abap2UI5 app can send, because the view vocabulary is the whole of UI5 XML
(ui5.md).
The portable profile is a subset of that vocabulary - the same view XML, the same JSON model, the same event wires, no new ABAP API - that every conforming non-UI5 frontend renders. An app whose views stay inside it runs unchanged on the UI5 frontend and on any portable renderer (UI5 Web Components first, later Adaptive Cards or native mobile).
It was chosen from what apps actually use: 61 rendered controls and 4 layout-data elements, which cover 73.7 % of the 247 core apps by controls; 64.8 % (160 apps) stay inside every rule of this page and run unchanged (section 10, portable-coverage.md).
- A portable app is an app whose every document (main view, popup,
popover) uses only the controls, members, binding forms, event wires,
event-argument descriptors, frontend actions and client API calls this
page allows.
portable-v1.jsonis the list a linter checks against. - A portable frontend implements the core protocol and MUST render every portable app correctly: every control of section 3, every member listed for it, every allowed binding form, event wire, descriptor and frontend action.
- A portable frontend MUST NOT fail on anything outside the profile. An
unknown property or aggregation is ignored (and SHOULD be logged); an
element of an unknown control or of a namespace outside
section 2 is replaced by a visible
placeholder; an unknown frontend action is skipped with a log line - the
same tolerance the UI5 frontend shows for an unknown action
(
FrontendAction.execute, abap2UI5app/webapp/core/FrontendAction.js). - The UI5 frontend renders every portable app (the profile is a subset of
the UI5 profile), but the tolerance rule above is not its: a UI5-profile
frontend has no "outside" - any UI5 element may appear - and an element
it cannot load (an unknown namespace) fails the view like any view that
does not build ([FA]
executeSystem, errors.md). The tolerance rule binds the portable renderers that are not UI5 frontends. (Revision 0.1 said "a portable frontend by construction"; the frontend suite showed the UI5 SPA failing the view on<x:Gadget xmlns:x="com.example.conformance"/>with a module load error.) - Frontend checks:
portable.default-aggregation,portable.unknown-property,portable.unknown-control,portable.excluded-action,portable.box-details,portable.timer,portable.set-title,portable.view-replaced.
- Documents. A MAIN view is a
sap.ui.core.mvc.View(<mvc:View>); a POPUP or POPOVER document is asap.ui.core.FragmentDefinition(<core:FragmentDefinition>). The root attributesdisplayBlockandheightare layout hints;xmlns/xmlns:<prefix>declare namespaces.core:requireis outside the profile. - Slots. A portable app uses the slots MAIN (
view_display), POPUP (popup_display,popup_destroy) and POPOVER (popover_display( xml by_id ),popover_destroy). The nested slots NEST and NEST2 are not in v1 (6 core apps use them; section 9), and the two sides of that are separate rules (decided in revision 0.3, open question 1):- A portable app MUST NOT use them (
nest_view_display,nest2_view_displayand their destroys are outside the client API of section 6). The abap2UI5 linter's portable rule reports the calls; an app that needs nested views is a UI5-profile app. - A portable renderer tolerates them: one that receives a NEST/NEST2
display MAY show a placeholder for it, but MUST process the action (it
is core protocol, ../spec/response.md)
without failing the roundtrip. Frontend check:
slots.nest-processed.
- A portable app MUST NOT use them (
- Namespaces.
sap.m,sap.ui.core,sap.ui.core.mvc,sap.ui.layout,sap.ui.layout.form,sap.tnt. - Elements. An element whose local name starts with an upper-case letter
is a control; a lower-case element in the parent's namespace is an
aggregation of the enclosing control. A control's default aggregation
MAY be written with or without its element (
<VBox><items>...</items></VBox>equals<VBox>...</VBox>); a frontend MUST accept both. - Universal attributes on every control:
id,class,visible(bindable),tooltip(text or binding),busy,busyIndicatorDelay,fieldGroupIds(accepted, no effect),binding(an element binding: the context of the relative bindings below it), and the aggregationslayoutData,customData,dependents(dependent controls are rendered hidden, e.g. a dialog opened later).Label.labelFor(an association) is accepted. - Ids. A frontend MUST keep every view id addressable within its slot:
the popover anchor (
openById), SET_FOCUS, SCROLL_TO andLabel.labelForaddress controls by the id the view gave them. - CSS classes.
classvalues are passed through. The UI5 spacing helpers (sapUiSmallMargin,sapUiTinyMarginTop, ...,sapUiContentPadding,sapUiResponsiveMargin; 18 of the 22 classes core apps use) MUST be honoured as margins/paddings of 0.25 / 0.5 / 1 / 2 rem (Tiny / Small / Medium / Large). Other classes are the app's, styled by its owncore:HTML<style>content - a selector written against the UI5 DOM (.sapMInputBaseInner) is not expected to match. - Tolerated elements -
sap.ui.core.CustomData,sap.m.FlexItemData,sap.ui.layout.GridData,sap.m.OverflowToolbarLayoutData- carry no UI. A frontend applies what it can (data-*forCustomData writeToDom, flex grow/shrink/basis, grid span, overflow priority) and MAY drop the rest; it MUST NOT fail on them.
Every control below MUST be rendered, and every member listed for it MUST be accepted - applied where the target has a counterpart, accepted without visual effect where Appendix A says "ignored". A member is in v1 when at least one core app or at least eight samples-controls apps use it (plus a few cheap ones added by hand); the universal attributes of section 2 are not repeated. The figures are core apps / samples-controls apps of the census.
| Control | Core / samples-controls apps | Properties | Aggregations | Events |
|---|---|---|---|---|
| sap.m.Page | 195 / 162 | backgroundDesign (0/6), enableScrolling (0/23), showFooter (0/2), showHeader (5/120), showNavButton (185/36), title (188/42), titleLevel (0/2) |
customHeader (2/34), footer (10/30), headerContent (7/4), subHeader (1/13) (default: content) |
navButtonPress (185/20) |
| sap.m.Shell | 193 / 15 | - | - (default: app) |
- |
| sap.m.VBox | 72 / 194 | alignItems (2/15), height (5/14), justifyContent (4/14), renderType (0/9), width (2/8), wrap (0/1) |
- (default: items) |
- |
| sap.ui.layout.form.SimpleForm | 70 / 115 | adjustLabelSpan (2/18), columnsL (1/44), columnsM (1/44), columnsXL (1/24), editable (65/110), emptySpanL (0/50), emptySpanM (0/50), emptySpanS (0/29), emptySpanXL (0/14), labelSpanL (3/65), labelSpanM (3/65), labelSpanS (2/41), labelSpanXL (2/24), layout (11/112), maxContainerCols (0/30), singleContainerFullSize (0/15), width (0/32) |
title (53/45) (default: content) |
- |
| sap.m.HBox | 35 / 64 | alignItems (12/25), height (0/4), justifyContent (1/18), renderType (0/13), width (0/7), wrap (7/2) |
- (default: items) |
- |
| sap.m.Panel | 15 / 71 | backgroundDesign (0/14), expandable (4/5), expanded (3/4), headerText (14/28), height (0/13), stickyHeader (0/1), width (5/36) |
headerToolbar (0/21) (default: content) |
expand (0/1) |
| sap.ui.layout.Grid | 13 / 26 | defaultSpan (11/25), hSpacing (0/17), width (0/11) |
- (default: content) |
- |
| sap.m.FlexBox | 7 / 54 | alignItems (5/36), columnGap (0/1), direction (1/12), fitContainer (0/25), gap (0/1), height (2/7), justifyContent (3/12), renderType (1/5), rowGap (0/1), width (1/5), wrap (1/25) |
- (default: items) |
- |
| sap.m.ScrollContainer | 4 / 24 | height (4/20), horizontal (1/15), vertical (4/22), width (0/12) |
- (default: content) |
- |
| sap.m.IconTabFilter | 4 / 35 | count (0/17), design (0/3), enabled (0/1), icon (2/16), iconColor (0/9), key (4/32), text (4/29) |
- (default: content) |
- |
| sap.m.IconTabBar | 3 / 30 | applyContentPadding (1/2), expandable (2/2), expanded (2/9), headerBackgroundDesign (0/3), headerMode (1/4), selectedKey (2/8) |
content (1/7), items (3/30) |
select (2/6) |
| sap.ui.layout.VerticalLayout | 2 / 174 | width (2/110) |
- (default: content) |
- |
| sap.ui.core.Title | 1 / 55 | text (1/55) |
- | - |
| sap.ui.layout.HorizontalLayout | 0 / 52 | allowWrapping (0/12) |
- (default: content) |
- |
| Control | Core / samples-controls apps | Properties | Aggregations | Events |
|---|---|---|---|---|
| sap.m.OverflowToolbar | 43 / 113 | height (0/12), style (0/22) |
- (default: content) |
- |
| sap.m.ToolbarSpacer | 37 / 117 | width (1/5) |
- | - |
| sap.m.Toolbar | 16 / 55 | height (0/12), style (1/0) |
- (default: content) |
- |
| sap.m.Bar | 2 / 40 | - | contentLeft (2/9), contentMiddle (0/9), contentRight (2/34) |
- |
| sap.m.OverflowToolbarButton | 2 / 37 | enabled (0/1), icon (2/37), text (2/31), type (0/30) |
- | press (2/12) |
| Control | Core / samples-controls apps | Properties | Aggregations | Events |
|---|---|---|---|---|
| sap.m.Text | 115 / 310 | emptyIndicatorMode (0/1), maxLines (0/1), renderWhitespace (1/2), text (102/307), textAlign (0/1), width (1/14), wrapping (1/42) |
- | - |
| sap.m.Label | 86 / 286 | design (0/8), required (2/8), showColon (0/1), text (76/285), textAlign (0/1), width (1/9), wrapping (0/17) |
- | - |
| sap.m.Title | 58 / 181 | level (10/53), text (51/178), textAlign (0/1), titleStyle (0/25), wrapping (1/43) |
- (default: content) |
- |
| sap.m.ObjectStatus | 17 / 51 | active (0/2), icon (2/6), inverted (0/3), state (11/50), text (16/51), title (6/18) |
- | press (0/1) |
| sap.m.Link | 14 / 94 | emphasized (0/2), enabled (0/1), endIcon (0/1), href (11/45), icon (0/1), target (13/31), text (12/93), wrapping (0/1) |
- | press (3/35) |
| sap.m.ObjectIdentifier | 7 / 50 | text (7/45), title (1/47), titleActive (0/3) |
- | titlePress (0/3) |
| sap.ui.core.HTML | 7 / 60 | content (5/60) |
- | - |
| sap.ui.core.Icon | 6 / 18 | alt (0/1), color (1/3), size (5/6), src (5/17), width (0/1) |
- | press (1/1) |
| sap.m.ObjectNumber | 5 / 50 | emphasized (0/14), number (5/50), state (2/29), unit (3/49) |
- | - |
| sap.tnt.InfoLabel | 4 / 4 | colorScheme (2/3), icon (1/1), text (4/4) |
- | - |
| sap.m.ProgressIndicator | 3 / 21 | displayOnly (0/4), displayValue (3/19), percentValue (3/21), showValue (3/7), state (3/9), width (0/1) |
- | - |
| sap.m.Image | 2 / 51 | alt (0/6), decorative (0/6), densityAware (0/15), height (1/11), src (2/49), width (1/26) |
- | - |
| Control | Core / samples-controls apps | Properties | Aggregations | Events |
|---|---|---|---|---|
| sap.m.Input | 87 / 117 | description (3/10), editable (7/1), enabled (17/1), maxLength (4/2), placeholder (14/39), showClearIcon (0/2), showSuggestion (1/12), showValueHelp (8/8), type (8/41), value (81/96), valueLiveUpdate (0/6), valueState (1/6), valueStateText (1/6), width (12/26) |
suggestionItems (1/10) |
change (0/10), liveChange (1/7), submit (12/1), suggestionItemSelected (0/3), valueHelpRequest (4/8) |
| sap.m.TextArea | 12 / 17 | editable (6/0), growing (3/1), growingMaxLines (2/1), maxLength (0/3), placeholder (3/8), rows (9/11), showExceededText (0/1), value (11/13), valueLiveUpdate (2/3), valueState (0/2), width (10/8), wrapping (1/0) |
- | liveChange (0/1) |
| sap.ui.core.Item | 12 / 132 | key (12/127), text (11/131) |
- | - |
| sap.m.CheckBox | 11 / 36 | editable (1/0), enabled (5/3), partiallySelected (0/2), required (0/1), selected (9/29), text (2/23), valueState (0/1), wrapping (0/1) |
- | select (2/11) |
| sap.m.Switch | 10 / 24 | customTextOff (1/2), customTextOn (1/2), enabled (3/2), state (10/23), type (1/4) |
- | change (8/5) |
| sap.m.SegmentedButton | 10 / 23 | enabled (0/1), selectedKey (9/16), width (0/5) |
items (10/23) |
selectionChange (4/9) |
| sap.m.SegmentedButtonItem | 10 / 23 | enabled (0/2), icon (4/13), key (10/16), text (10/18), width (0/2) |
- | - |
| sap.m.Select | 8 / 85 | editable (1/2), enabled (1/1), forceSelection (3/9), selectedKey (7/80), valueState (0/1), valueStateText (0/1), width (2/11) |
- (default: items) |
change (1/11), liveChange (0/1) |
| sap.m.DatePicker | 8 / 23 | dateValue (2/0), displayFormat (3/7), editable (2/0), placeholder (1/2), required (0/3), value (4/16), valueFormat (6/6), valueState (0/4), valueStateText (0/4), width (0/4) |
- | change (0/4) |
| sap.m.SearchField | 7 / 29 | placeholder (7/8), showRefreshButton (0/2), value (5/6), width (7/27) |
- | liveChange (2/3), search (5/15), suggest (0/1) |
| sap.m.ComboBox | 3 / 36 | placeholder (0/10), selectedKey (3/16), showClearIcon (0/2), value (0/8), valueState (0/3), valueStateText (0/3), width (0/5) |
- (default: items) |
change (0/4) |
| sap.m.MultiInput | 3 / 14 | enabled (1/0), placeholder (0/6), showSuggestion (0/9), showValueHelp (0/11), value (0/4), valueState (0/2), width (1/9) |
tokens (3/6) (default: suggestionItems) |
change (0/2), tokenUpdate (0/2), valueHelpRequest (1/1) |
| sap.m.Token | 3 / 12 | editable (3/0), key (3/9), selected (3/0), text (3/12) |
- | - |
| sap.m.MultiComboBox | 2 / 21 | editable (1/0), placeholder (0/7), selectedKeys (1/8), valueState (0/2), valueStateText (0/2), width (0/14) |
- (default: items) |
selectionChange (0/3), selectionFinish (0/8) |
| sap.m.StepInput | 2 / 4 | displayValuePrecision (0/1), editable (0/1), enabled (0/1), max (0/2), min (1/2), step (0/2), value (2/4), valueState (0/2), width (0/4) |
- | change (0/1) |
| sap.ui.core.ListItem | 1 / 19 | additionalText (1/11), key (0/18), text (1/19) |
- | - |
| sap.m.DateTimePicker | 1 / 10 | dateValue (1/0), displayFormat (0/3), editable (1/0), placeholder (0/2), required (0/3), value (0/7), valueFormat (0/6), valueState (0/4), valueStateText (0/3), width (0/2) |
- | change (0/4) |
| Control | Core / samples-controls apps | Properties | Aggregations | Events |
|---|---|---|---|---|
| sap.m.Button | 169 / 273 | ariaHasPopup (0/30), enabled (8/33), icon (59/93), text (149/242), type (83/136), width (4/20) |
- | press (167/215) |
| sap.m.ToggleButton | 1 / 43 | enabled (0/1), icon (1/15), pressed (1/24), text (1/31), type (0/1) |
- | press (1/10) |
| Control | Core / samples-controls apps | Properties | Aggregations | Events |
|---|---|---|---|---|
| sap.m.Column | 65 / 69 | demandPopin (2/50), hAlign (3/56), importance (0/1), mergeDuplicates (2/2), minScreenWidth (2/49), width (8/48) |
- (default: header) |
- |
| sap.m.ColumnListItem | 65 / 69 | selected (10/8), type (8/18), vAlign (8/29) |
- (default: cells) |
detailPress (1/0), press (7/6) |
| sap.m.Table | 63 / 63 | alternateRowColors (0/1), growing (13/8), growingScrollToLoad (3/1), growingThreshold (5/3), headerText (10/12), inset (0/29), mode (11/17), noDataText (2/3), popinLayout (0/8), sticky (4/8), width (6/16) |
columns (63/62), headerToolbar (38/39), infoToolbar (0/11) (default: items) |
itemPress (0/5), selectionChange (0/5) |
| sap.m.List | 24 / 74 | growing (0/6), growingThreshold (0/4), headerText (15/35), includeItemInSelection (0/5), mode (7/13), noDataText (5/7), showSeparators (3/9), width (1/4) |
headerToolbar (0/10) (default: items) |
delete (0/4), itemPress (0/1), selectionChange (7/5) |
| sap.m.StandardListItem | 18 / 59 | counter (0/7), description (14/39), highlight (1/5), icon (6/33), iconDensityAware (0/29), iconInset (1/31), info (9/9), infoState (1/5), selected (6/3), title (18/59), type (1/17), wrapping (2/1) |
- (default: actions) |
detailPress (1/1), press (0/7) |
| sap.m.CustomListItem | 5 / 7 | selected (1/0) |
- (default: content) |
- |
| sap.m.Tree | 4 / 9 | headerText (4/0), mode (0/4), sticky (0/1) |
headerToolbar (0/3) (default: items) |
toggleOpenState (0/1) |
| sap.m.StandardTreeItem | 3 / 8 | icon (0/1), title (3/8) |
- | - |
| Control | Core / samples-controls apps | Properties | Aggregations | Events |
|---|---|---|---|---|
| sap.m.Dialog | 46 / 33 | contentHeight (10/5), contentWidth (23/8), draggable (4/2), horizontalScrolling (1/0), icon (3/0), resizable (5/3), showHeader (0/1), state (1/1), stretch (5/0), title (20/26), type (1/9), verticalScrolling (3/3) |
beginButton (2/27), buttons (38/3), customHeader (0/2), endButton (3/21), footer (0/1), subHeader (0/1) (default: content) |
afterClose (30/0) |
| sap.m.Popover | 7 / 12 | contentHeight (0/3), contentWidth (5/6), modal (0/1), placement (7/10), showHeader (0/6), title (7/5) |
footer (2/4) (default: content) |
afterClose (0/1) |
| Control | Core / samples-controls apps | Properties | Aggregations | Events |
|---|---|---|---|---|
| sap.m.MessageStrip | 153 / 45 | enableFormattedText (1/1), showCloseButton (0/7), showIcon (145/27), text (150/45), type (152/27) |
- | close (0/1) |
| Control | Core / samples-controls apps | Properties | Aggregations | Events |
|---|---|---|---|---|
| sap.ui.core.CustomData (tolerated) | 3 / 11 | key (3/11), value (3/10), writeToDom (2/4) |
- | - |
| sap.m.FlexItemData (tolerated) | 1 / 37 | baseSize (1/6), growFactor (1/29), shrinkFactor (0/8) |
- | - |
| sap.ui.layout.GridData (tolerated) | 0 / 37 | linebreak (0/11), span (0/36) |
- | - |
| sap.m.OverflowToolbarLayoutData (tolerated) | 0 / 18 | priority (0/18) |
- | - |
Property values are strings in the view XML; { starts a binding unless it
is escaped as \{.
| Form | Example | Core apps (samples-controls) | v1 |
|---|---|---|---|
| absolute path | {/MV_VALUE}, {/S_SCREEN/COLOR_01} |
160 (421) | MUST - two-way for value-like properties (Input.value, CheckBox.selected, Switch.state, Select.selectedKey, SegmentedButton.selectedKey, ColumnListItem.selected, ...): the frontend writes user edits into the model and sends them as the model delta of the next event (../spec/request.md) |
| list binding of an aggregation | items="{/T_TAB}" + one template child |
133 (387) | MUST - the template is cloned per array entry; relative paths resolve per entry |
| relative path | {TITLE} |
91 (312) | MUST - inside a template or an element binding |
| object binding | {path:'/T_TAB', templateShareable:false} |
15 (202) | MUST for the keys path, parts, type, formatOptions, constraints, formatter (below), targetType, mode; list bindings: path, sorter: {path, descending}, templateShareable (no effect), length, startIndex |
| string composite | {/MV_PERCENT} % |
11 (97) | MUST - concatenate the formatted parts |
| expression binding | {= ${/QUANTITY} > 500 } |
11 (138) | MUST for the restricted grammar below; anything else is outside the profile |
| escaped braces | .c \{ color:red \} |
9 (52) | MUST - unescape |
| typed binding | {path:'/AMOUNT', type:'sap.ui.model.type.Integer'} |
3 (89) | MUST for sap.ui.model.type. String, Integer, Float, Currency (with parts: [amount, currency]), Date, Time, DateTime; the formatOptions and constraints below; a parse error sets the control's value state to error |
composite parts |
{parts:['/AMOUNT','/CURRENCY'], type:...} |
3 (62) | MUST, with a v1 type or a v1 formatter |
| frontend formatters | formatter: 'Formatter.DateAbapDateToDateObject' |
4 (36) | MUST for Formatter.DateCreateObject, Formatter.DateAbapDateToDateObject, Formatter.DateAbapDateTimeToDateObject (ABAP DATS/TIMS/ISO strings to dates) |
device> model |
{device>/system/phone} |
1 (2) | MUST - the frontend provides /system/{phone,tablet,desktop}, /resize/{width,height}, /support/touch, /orientation/{portrait,landscape} |
| other named models | {L0>FNAME}, {meta>ENTITY} |
6 (8) | excluded (XML templating and OData metadata) |
{i18n>key} |
- | 0 (0) | excluded (unused) |
sap.ui.model.odata.type.* |
- | 1 (1) | excluded |
- formatOptions:
minFractionDigits,maxFractionDigits,minIntegerDigits,maxIntegerDigits,groupingEnabled,decimals,style,pattern,source.pattern,showMeasure,showNumber,currencyCode,preserveDecimals,UTC. - constraints:
minimum,maximum,minLength,maxLength. - Expression grammar (restricted). References
${/absolute},${relative},${device>/path}; string, number, boolean andnullliterals; the operators! && || ?: === !== == != < <= > >= + - * / %and parentheses; the member.length; the functionsMath.max,Math.min,Math.abs,Math.round,Math.floor,Math.ceiland the string methods.toUpperCase(),.toLowerCase(),.trim(),.indexOf(),.includes(),.startsWith(). Everything else - RegExp,odata.*,encodeURIComponent, arbitrary JavaScript - is outside the profile (one core app uses such a call). - A frontend MAY evaluate the bindings any way it likes; what counts is the value the control shows and the value the model receives.
The wire forms are those of the UI5 profile (ui5.md),
written by the backend's z2ui5_cl_ui5_srv_event (abap2UI5
src/01/02/z2ui5_cl_ui5_srv_event.clas.abap, get_event,
get_event_client):
| Wire (in the attribute) | From | Wires in all corpora / core apps | v1 |
|---|---|---|---|
.eB(['EVENT']) |
client->_event( ) |
1,198 / 192 | MUST |
.eB(['EVENT'], arg1, ...) |
client->_event( val t_arg ) |
579 | MUST, arguments per the descriptor table |
.eB(['___ZZZ_NAL']) |
client->_event_nav_app_leave( ) |
198 / 180 | MUST - fires the reserved leave event (../spec/navigation.md) |
.eF('ACTION', arg...) |
_event_client( ), a wired follow_up_action( ) |
583 / 22 | MUST for the frontend actions of section 6, run on the event without a roundtrip |
.eBP($event, true, ['EVENT'], ...) |
s_ctrl-check_prevent_default |
18 | MUST - cancel the native default, then roundtrip |
.eBP($event, <expr>, ...) |
s_ctrl-prevent_default_expr |
excluded (an expression over control objects) | |
['EVENT', false, false, false, queueLast, noBusy] |
s_ctrl-check_queue_last, check_no_busy |
37 / 31 | MUST - keep only the last firing while a roundtrip runs; no busy overlay |
| quoted arguments | s_ctrl-check_arg_literal |
1 | MUST - every argument is a string |
Event-argument descriptors. The arguments of .eB(...) are evaluated
when the event fires:
| Descriptor | Meaning | Core / samples-controls apps | v1 |
|---|---|---|---|
'ROW_1' |
a constant | 15 / 150 | MUST |
${REL_PATH}, e.g. ${ID} |
a field of the binding context (row) of the control that fired - how a table or list row identifies itself | 29 / 21 | MUST - evaluated in the clicked item's context |
${/ABS_PATH} |
the current model value | 2 / 1 | MUST |
${$source>/prop} |
a property of the control that fired | 4 / 22 | MUST for every v1 property of that control |
${$parameters>/name} |
an event parameter | 23 / 168 | MUST for the closed list below |
JSON / message template starting with { or $ |
passed through as data | 5 / 13 | MUST (meaningful for frontend actions) |
${$parameters>/selectedItem}.getKey(), .getBindingContext().getPath(), .indexOfItem() |
UI5 object API | 9 / 114 | excluded - bind selectedKey / selected two-way or pass ${REL} instead |
$event.getSource()..., $event.mParameters... |
the raw UI5 event | 7 / 83 | excluded |
$controller.slotValue( ), textPath( ) |
frontend controller helpers | 1 / 0 | excluded |
Event parameters (${$parameters>/name}) a portable frontend MUST
provide:
| Control | Event | Parameters |
|---|---|---|
| sap.m.Input | liveChange, submit, change / suggest |
value / suggestValue |
| sap.m.TextArea | liveChange, change |
value |
| sap.m.SearchField | search / liveChange / suggest |
query, refreshButtonPressed (false), clearButtonPressed (false) / newValue / suggestValue |
| sap.m.CheckBox | select |
selected |
| sap.m.Switch | change |
state |
| sap.m.ToggleButton | press |
pressed |
| sap.m.IconTabBar | select |
key, selectedKey |
| sap.m.DatePicker, sap.m.DateTimePicker | change |
value, valid |
| sap.m.StepInput | change |
value |
| sap.m.MultiInput | change / tokenUpdate |
value / type |
| sap.m.MultiComboBox, sap.m.Table, sap.m.List | selectionChange |
selected |
| sap.m.Panel | expand |
expand |
Parameters that are UI5 objects (item, listItem, selectedItem,
column, draggedControl, ...) are excluded. The event names a frontend
fires are exactly the events lines of section 3.
The follow-up actions of a response (T_CUSTOM,
../spec/actions.md) and the .eF(...) wires a portable
frontend MUST perform:
| Action | Core apps | Notes |
|---|---|---|
MESSAGE_TOAST show |
53 (message_toast_display) + 6 |
toast with duration, onClose |
MESSAGE_BOX show / alert / confirm / information / warning / error / success |
45 (message_box_display) + 6 |
dialog with type, text, title, actions, onClose event (the pressed action is its argument), details |
VIEW_SLOTS destroy POPUP / POPOVER |
5 | the frontend close of cs_event-popup_close / popover_close |
SET_FOCUS |
20 | focus the control with that id (optional selection start/end) |
START_TIMER |
8 | fire the event after the delay |
DOWNLOAD_B64_FILE, CLIPBOARD_COPY, URLHELPER, OPEN_NEW_TAB |
4, 4, 3, 2 | browser (or platform share/intent) APIs |
SCROLL_TO, SCROLL_INTO_VIEW |
2, 1 | scroll the element with that id |
SET_TITLE, SET_FAVICON, LOCATION_RELOAD, SYSTEM_LOGOUT, STORE_DATA, KEYBOARD_SHORTCUT, PLAY_AUDIO |
1-2 each | MAY be a no-op where the platform has no counterpart |
BUSY_INDICATOR show/hide, INVISIBLE_MESSAGE announce, THEMING setTheme (via CONTROL_GLOBAL) |
3 | busy overlay, aria-live region, theme switch |
SET_PUSH_STATE, HASH_REPLACE, HASH_BACK, HASH_ATTACH_CHANGED, SET_NAV_ROUTING, SET_APP_STATE_ACTIVE |
1-3 each | URL hash handling (../spec/navigation.md); MAY be a no-op without a URL (native) |
SET_SIZE_LIMIT |
1 | a UI5 list limit - MAY be a no-op |
Names on the client API and on the wire are not the same list
(decided in revision 0.3,
open question 10).
The table above names what a portable app may call. The navigation family
among them is folded by the backend into the one ROUTER system action
(../spec/actions.md,
../spec/navigation.md, [CL]
follow_up_action, [FE] check_on_event): a renderer never receives
SET_PUSH_STATE, HASH_REPLACE, HASH_ATTACH_CHANGED, SET_NAV_ROUTING
or SET_APP_STATE_ACTIVE - it receives ROUTER with options, and
HASH_BACK as a follow-up action. portable-v1.json says both:
actions.api (what an app may call; frontendActions.allowed is the same
list, kept for readers of revision 0.2) and actions.wire (what a renderer
implements):
Client API (actions.api) |
What the renderer receives (actions.wire) |
|---|---|
SET_FOCUS |
SET_FOCUS (T_CUSTOM, .eF) |
START_TIMER |
START_TIMER (T_CUSTOM, .eF) |
DOWNLOAD_B64_FILE |
DOWNLOAD_B64_FILE (T_CUSTOM, .eF) |
CLIPBOARD_COPY |
CLIPBOARD_COPY (T_CUSTOM, .eF) |
URLHELPER |
URLHELPER (T_CUSTOM, .eF) |
OPEN_NEW_TAB |
OPEN_NEW_TAB (T_CUSTOM, .eF) |
SCROLL_TO |
SCROLL_TO (T_CUSTOM, .eF) |
SCROLL_INTO_VIEW |
SCROLL_INTO_VIEW (T_CUSTOM, .eF) |
SET_TITLE |
SET_TITLE (T_CUSTOM, .eF) |
SET_FAVICON |
SET_FAVICON (T_CUSTOM, .eF) |
LOCATION_RELOAD |
LOCATION_RELOAD (T_CUSTOM, .eF) |
SYSTEM_LOGOUT |
SYSTEM_LOGOUT (T_CUSTOM, .eF) |
STORE_DATA |
STORE_DATA (T_CUSTOM, .eF) |
KEYBOARD_SHORTCUT |
KEYBOARD_SHORTCUT (T_CUSTOM, .eF) |
PLAY_AUDIO |
PLAY_AUDIO (T_CUSTOM, .eF) |
SET_PUSH_STATE |
the ROUTER option setPushState - never SET_PUSH_STATE itself |
HASH_REPLACE |
the ROUTER option setHashReplace - never HASH_REPLACE itself |
HASH_BACK |
HASH_BACK (T_CUSTOM, .eF) |
HASH_ATTACH_CHANGED |
the ROUTER option setHashEvent - never HASH_ATTACH_CHANGED itself |
SET_NAV_ROUTING |
the ROUTER option setNavRouting - never SET_NAV_ROUTING itself |
SET_APP_STATE_ACTIVE |
the ROUTER option setAppStateActive - never SET_APP_STATE_ACTIVE itself |
SET_SIZE_LIMIT |
SET_SIZE_LIMIT (T_CUSTOM, .eF) |
(MESSAGE_TOAST) |
MESSAGE_TOAST show (T_CUSTOM or .eF, directly or as a CONTROL_GLOBAL target) |
(MESSAGE_BOX) |
MESSAGE_BOX show / alert / confirm / information / warning / error / success (T_CUSTOM or .eF, directly or as a CONTROL_GLOBAL target) |
(BUSY_INDICATOR) |
BUSY_INDICATOR show / hide (T_CUSTOM or .eF, directly or as a CONTROL_GLOBAL target) |
(INVISIBLE_MESSAGE) |
INVISIBLE_MESSAGE announce (T_CUSTOM or .eF, directly or as a CONTROL_GLOBAL target) |
(THEMING) |
THEMING setTheme (T_CUSTOM or .eF, directly or as a CONTROL_GLOBAL target) |
(VIEW_SLOTS) |
VIEW_SLOTS destroy (T_CUSTOM or .eF, directly or as a CONTROL_GLOBAL target) |
System actions (T_SYSTEM): VIEW_SLOTS display / destroy, ROUTER sync; the ROUTER options: setNavRouting, checkNavAppCall, navAppCallPrevApp, navAppCallPrevId, setPushState, setHashReplace, setHashEvent, setAppStateActive. MAY be a no-op where the platform has no counterpart: ROUTER, HASH_BACK, SET_SIZE_LIMIT.
Excluded: CONTROL_BY_ID (open-ended UI5 method calls, 16 core apps;
a closed whitelist is a v1.1 candidate), BINDING_CALL (v1.1 candidate),
BIND_ELEMENT, SET_ODATA_MODEL, SMART_VARIANT_INIT,
FILTER_BAR_VARIANT_INIT, CROSS_APP_NAV_TO_EXT, CROSS_APP_NAV_TO_PREV_APP,
SET_TITLE_LAUNCHPAD, and the CONTROL_GLOBAL targets ICON_POOL, POPUP,
FORMATTING.
Client API of a portable app (backend side): view_display,
popup_display / popup_destroy, popover_display / popover_destroy,
message_toast_display, message_box_display, follow_up_action (the
actions above), _event, _event_client, _event_nav_app_leave, _bind;
nav_app_call / nav_app_leave and get_event_arg are server-side and
transparent to the frontend. Not in v1: nest_view_display /
nest2_view_display, view_display( switch_default_model_path ).
- Namespaces and families:
sap.ui.comp(smart controls),sap.uxap,sap.f(DynamicPage and FlexibleColumnLayout are v1.1 candidates),sap.ui.table(v1.1 candidate),sap.ui.unified,sap.suite.*,sap.viz,sap.gantt,sap.ui.vbm,sap.ui.vk,sap.ui.codeeditor,sap.ui.integration,sap.ndc,sap.ui.webc.*, drag and drop (sap.ui.core.dnd,sap.f.dnd),sap.m.plugins, andhtml:elements in a view (usecore:HTML). - abap2UI5 custom controls
z2ui5.cc.*(19 core apps): frontend extensions bound to the UI5 runtime. Several are device or browser services that map well to other platforms; each needs a portable spec of its own and is not part of the view profile. - XML templating (
template:if/repeat/with). - UI5 object access in event arguments,
prevent_default_expr, named models other thandevice,odata.*types, app formatter functions,core:require, i18n models. - Members not listed in section 3 (Table
insetis listed,popinLayouttoo; ColumnpopinDisplay, ComboBoxshowSecondaryValues, InputsuggestionColumns, Imagemode, ... are not) - ignored by a portable frontend, never an error.
- Two-way binding is how a portable app reads UI state - 81 core apps
bind
Input.value, 10Switch.state, 10ColumnListItem.selected, 9CheckBox.selected, 9SegmentedButton.selectedKey. The frontend keeps the model in sync and sends the changed paths with the next event, as the UI5 frontend does; this replaces every.getKey()/$eventconstruct. - Row identity comes from the binding context:
${REL}arguments andpresswires of list items are evaluated against the clicked row. - Back navigation is everywhere (
showNavButton+navButtonPress=_event_nav_app_leave( ), 185 core apps): implement the Page header first. - Popups are common (Dialog in 46 core apps); popovers need stable ids for their anchor.
- Messages: MessageStrip (153 core apps), toast (53), message box (45) - all three belong in a first renderer.
- Forms are SimpleForm (70 core apps) with a flat Label/field sequence that the frontend has to group (Appendix A).
- Tables are
sap.m.Table(63 core apps) withColumnListItemtemplates; growing is local paging over rows already in the model.
Ordered by core apps they would unblock; taking all of them lifts control coverage from 73.7 % to 82.6 % of core apps. None of them is part of v1.
| Family | Controls | Core apps blocked in v1 | Web Component | Fit / note |
|---|---|---|---|---|
| grid table | sap.ui.table.Table, Column, RowAction, RowActionItem | 7 | ui5-table (+ ui5-table-row-action, ui5-table-virtualizer) | adapt: Column label + template instead of header/cells; visibleRowCount/selectionMode/rowActionTemplate; fixed columns and column menu (sort/filter events with $parameters>/column objects) not portable |
| message popover | sap.m.MessagePopover, MessageItem, MessageView | 4 (3 sole) | none - compose ui5-popover/ui5-dialog + ui5-list (ui5-li with highlight per type) | compose |
| page layouts | sap.f.DynamicPage (+Title, Header), sap.f.FlexibleColumnLayout, sap.m.NavContainer | 3 + 3 + 3 | ui5-dynamic-page/-title/-header, ui5-flexible-column-layout | adapt; NavContainer needs CONTROL_BY_ID to/back -> define a portable "page switch" |
| value-help dialogs | sap.m.TableSelectDialog, SelectDialog | 3 (2 sole) | none - compose ui5-dialog + ui5-input search + ui5-table/ui5-list | compose; search/confirm events with $parameters>/value, selected rows via two-way selected |
| quick view | sap.m.QuickView, QuickViewPage, QuickViewGroup, QuickViewGroupElement | 3 | none - compose ui5-popover | compose |
| menus | sap.m.Menu, MenuItem, MenuButton | 2 | ui5-menu, ui5-menu-item, ui5-button opener | direct |
| small inputs | TimePicker, Slider, RadioButton/RadioButtonGroup, RatingIndicator | 1 each (+ many in samples-controls: Slider 37, RadioButton 15) | ui5-time-picker, ui5-slider, ui5-radio-button (group via name), ui5-rating-indicator | direct |
| object display | ObjectAttribute, ObjectHeader, Avatar, FormattedText, Carousel, Breadcrumbs | 1 each (samples-controls: 43, 26, 40, …) | compose / ui5-avatar / limited HTML / ui5-carousel / ui5-breadcrumbs | mixed |
| full Form | sap.ui.layout.form.Form, FormContainer, FormElement (+ ResponsiveGridLayout) | 0 (18 samples-controls) | ui5-form, ui5-form-group, ui5-form-item | direct (simpler than SimpleForm) |
| ResponsivePopover | sap.m.ResponsivePopover | 0 (18) | ui5-responsive-popover | direct |
| nested views | nest_view_display, nest2_view_display |
3 (+3 with other blockers) | render a second view document into the control with the given id | protocol feature, no new control |
| CONTROL_BY_ID whitelist | open/close/openBy/toggleBy (Dialog, Popover), setExpanded (Panel), focus, addStyleClass/removeStyleClass/toggleStyleClass, setText, setVisible |
5 among v1-control-covered apps (16 overall) | renderer implements the named methods on its own components | defines the portable part of an open-ended action |
| BINDING_CALL | client-side filter/sort of a bound list |
2 | renderer-side filter/sort of the template rows | needs a declarative filter/sort spec |
The list is drawn from a census of every app in the sample corpora, run on 2026-10-03:
- Corpora. The core corpus (247 apps with a view) is abap2UI5/samples (138), abap2UI5/samples-stack (32) and addon and real-world apps (77: popups, selection-screen, sapgui, abap-cloud-gui, admin-cockpit, agent). abap2UI5/samples-controls (642 ports of the UI5 demo kit) is reported separately: it is built to show every control, so it is a stress test, not a usage sample, and it has no knee in its coverage curve.
- Reconstruction, not regex. The exact view XML of every document of
every class (main view, popups, popovers, fragments) comes from the
abap2UI5 linter's view reconstruction (
prepareAbap( )of@abap2ui5/linter0.8.5), patched in one place so event-handler expressions (_event,_event_client,follow_up_action,_event_nav_app_leave) keep the raw ABAP call and wire shapes, arguments and frontend actions can be classified. Members are classified as property / event / aggregation / association from the linter's UI5 metadata snapshot, with inheritance. Client API calls andfollow_up_action( )call sites come from a scan of the ABAP source with comments and literals blanked. - "Fully covered" means every control an app uses, in any of its documents, is in the set; "runs unchanged" adds members, binding forms, argument descriptors, frontend actions and client API.
- Caveats. 20 addon launcher classes built with the legacy
z2ui5_cl_xml_viewAPI are not replayed (their popups are counted); 6 addon classes reconstruct only partly (what was found counts); argument classification of variables built at runtime is approximate; an older duplicate of abap-cloud-gui is not counted twice. - Reproduce. The census scripts are in
../tools/portable-census/, as they were run;portable-v1.jsonis regenerated from the census proposal withnode scripts/gen-portable-profile.mjs <portable-proposal.md>and this page's generated sections withnode scripts/render-portable.mjs(npm testfails when the two are out of step).
How each v1 control maps to UI5 Web Components 2.x (@ui5/webcomponents,
@ui5/webcomponents-fiori; tag, attribute, slot and event names checked
against the 2.27.2 custom-elements.json manifests). direct: one
component, names translate 1:1; adapt: a component exists, structure,
values or events need translating; compose: no component, built from
HTML/CSS or several components.
- sap.m.Page -> ui5-page (fiori) + ui5-bar in slot header/footer (adapt).
ui5-pagehas no title/nav button: build the header as<ui5-bar slot="header">withstartContent=<ui5-button icon="nav-back" design="Transparent">(only whenshowNavButton), default slot =<ui5-title>withtitle,endContent=headerContent.customHeaderreplaces that bar;subHeader= a second bar;footer(a Toolbar/OverflowToolbar/Bar) -> slotfooter(fixed-footer).showHeader=falsedrops the bar,enableScrolling=false->no-scrolling,backgroundDesign->background-design.navButtonPress= click of the nav button. Not in v1: aggregationlandmarkInfo(0/1). - sap.m.Shell -> (none) - plain root (compose). App frame only. Render its single child full-height;
appWidthLimited(default true) = centred max-width (~1280px) letterbox. Do NOT map toui5-shellbar(that is a header bar, not a frame). Not in v1: propertyappWidthLimited(0/1). - sap.m.VBox -> (none) - (compose).
alignItems/justifyContent/wrap/width/heightare CSS flexbox one-to-one (Start->flex-start, End->flex-end, Center, Stretch, SpaceBetween->space-between, …).renderTypeignored. Not in v1: propertyfitContainer(0/4), propertybackgroundDesign(0/1). - sap.ui.layout.form.SimpleForm -> ui5-form + ui5-form-group + ui5-form-item (adapt). SimpleForm content is a FLAT sequence; the renderer must group it: a
core:Title(orToolbar/Title) opens a new<ui5-form-group header-text>; eachLabelopens a new<ui5-form-item>(the label goes to slotlabelContent) and every following field until the next Label/Title goes to the item's default slot.labelSpanXL/L/M/S->label-span="S12 M4 L4 XL4"(same notation),emptySpan*->empty-span,columnsXL/L/M->layout="S1 M1 L2 XL2",titleaggregation ->header-text.layout/adjustLabelSpan/singleContainerFullSize/maxContainerColsignored.editableonly changes label/field density in UI5 - no WC counterpart (ignore). Not in v1: propertybackgroundDesign(0/5), aggregationtoolbar(0/3), eventvalidateFieldGroup(0/1). - sap.m.HBox -> (none) - (compose). As VBox, row direction.
wrap="Wrap"->flex-wrap:wrap. Not in v1: propertybackgroundDesign(0/2), propertyfitContainer(0/1). - sap.m.Panel -> ui5-panel (adapt).
headerText->header-text; UI5 panels are NOT collapsible by default, WC panels are: setfixedunlessexpandable=true;expanded->!collapsed;headerToolbar-> slotheader;width/heightCSS;expand<-toggle($parameters>/expand=!collapsed).backgroundDesign-> CSS only. Not in v1: propertyaccessibleRole(0/2). - sap.ui.layout.Grid -> (none) - CSS grid, 12 columns (compose).
defaultSpan="XL3 L3 M6 S12"-> per-breakpointgrid-column: span n(UI5 breakpoints S<600, M<1024, L<1440, XL); children may carryGridData span/linebreak/indent(tolerated).hSpacing/vSpacing(rem) ->column-gap/row-gap. Not in v1: propertycontainerQuery(0/3), propertydefaultIndent(0/2), propertyvSpacing(0/5), propertyposition(0/1). - sap.m.FlexBox -> (none) - flex (compose).
direction(Row/Column/RowReverse/ColumnReverse) ->flex-direction;fitContainer-> height:100%;gap/rowGap/columnGap-> CSS gap. - sap.m.ScrollContainer -> (none) - (compose).
vertical/horizontal->overflow-y/overflow-x(UI5 default: horizontal true, vertical false);width/heightCSS. SCROLL_TO / SCROLL_INTO_VIEW actions address it by id. Not in v1: propertyfocusable(0/2). - sap.m.IconTabFilter -> ui5-tab (adapt).
text,icon(sap-icon://x ->icon="x"),key-> keep asdata-key(WC tabs have no key),count->additional-text,enabled=false->disabled,design->design, content -> default slot.iconColor(Positive/Critical/Negative) -> tabdesign. Not in v1: propertyshowAll(0/7), aggregationitems(0/5), propertyinteractionMode(0/3). - sap.m.IconTabBar -> ui5-tabcontainer (adapt).
items-> tabs;selectedKey(two-way) ->selectedon the tab whose key matches, written back ontab-select;select<-tab-selectwith$parameters>/keyand$parameters>/selectedKey= the tab's key;expandable/expanded->collapsed;headerBackgroundDesign->header-background-design. The IconTabBar-levelcontentaggregation (shared content) has no slot: render it below the tab strip. Not in v1: propertybackgroundDesign(0/2), propertystretchContentHeight(0/2), propertyupperCase(0/5), propertyenableTabReordering(0/3), propertytabDensityMode(0/2), propertytabsOverflowMode(0/1), propertymaxNestingLevel(0/1). - sap.ui.layout.VerticalLayout -> (none) - block (compose). Children stacked;
widthCSS. - sap.ui.core.Title -> group header of ui5-form-group (inside forms); ui5-title elsewhere (adapt). Only
textis used (andlevel). Inside SimpleForm it is a group separator, not a visible control of its own. - sap.ui.layout.HorizontalLayout -> (none) - inline-flex (compose).
allowWrapping->flex-wrap.
- sap.m.OverflowToolbar -> ui5-toolbar (adapt). Toolbar children must be toolbar items: Button/OverflowToolbarButton ->
ui5-toolbar-button, ToolbarSpacer ->ui5-toolbar-spacer, Select ->ui5-toolbar-select/ui5-toolbar-select-option, anything else (Title, Label, Input, SearchField, SegmentedButton, …) wrapped inui5-toolbar-item.style="Clear"/design="Transparent"->design="Transparent".OverflowToolbarLayoutData priority->overflow-priority(NeverOverflow ->NeverOverflow, AlwaysOverflow ->AlwaysOverflow). Not in v1: propertyactive(0/3), eventpress(0/3), propertydesign(0/4), propertyenabled(0/1), propertywidth(0/5), propertyariaHasPopup(0/1). - sap.m.ToolbarSpacer -> ui5-toolbar-spacer (direct).
width->width(fixed spacer); without width it is the flexible spacer. Outside aui5-toolbar(e.g. inui5-bar) use aflex:1div. - sap.m.Toolbar -> ui5-toolbar (or ui5-bar) (adapt). Same mapping as OverflowToolbar. Most uses are the
headerToolbarof a Table/List/Panel (Title + Spacer + Buttons). Not in v1: propertywidth(0/1), propertydesign(0/1), propertyactive(0/1). - sap.m.Bar -> ui5-bar (direct).
contentLeft-> slotstartContent,contentMiddle-> default slot,contentRight-> slotendContent;design(Header/SubHeader/Footer) ->design. - sap.m.OverflowToolbarButton -> ui5-toolbar-button (direct). Icon-only in the bar, text shown in the overflow ->
show-overflow-text+text;type->design(as Button);press<-click.
- sap.m.Text -> ui5-text (direct).
text-> text content;wrapping=false->max-lines="1";maxLines->max-lines;renderWhitespace-> CSSwhite-space:pre-wrap;emptyIndicatorMode->empty-indicator-mode;textAlign/widthCSS. - sap.m.Label -> ui5-label (direct).
text,required,showColon->show-colon,wrapping->wrapping-type,labelFor->for(needs the target's DOM id);design="Bold"/width/textAlignCSS. Not in v1: propertydisplayOnly(0/2), propertywrappingType(0/1). - sap.m.Title -> ui5-title (direct).
text-> text content;level(H1..H6, Auto) ->level;titleStyle->size;wrapping=true->wrapping-type="Normal". A Title with acontentchild (link) renders that child inside. Not in v1: propertywrappingType(0/1). - sap.m.ObjectStatus -> ui5-tag (non-interactive) or styled text (adapt). No exact counterpart.
stateNone/Success/Warning/Error/Information/IndicationNN ->ui5-tag designNeutral/Positive/Critical/Negative/Information/Set1..(color-scheme) - BUT a tag renders as a pill; apps expect coloured text (+ icon). Recommended:<span>with theming colour vars (--sapPositiveTextColor, …) + optionalui5-icon; useui5-tagonly forinverted=true.title-> "title: " prefix;active/press->ui5-tag interactive+click. - sap.m.Link -> ui5-link (direct).
text-> text content,href,target,enabled=false->disabled,emphasized->design="Emphasized",subtle->design="Subtle",wrapping->wrapping-type,icon/endIcon->icon/end-icon;press<-click(do not navigate when a press wire is set and no href). Not in v1: propertysubtle(0/1), propertyariaHasPopup(0/5). - sap.m.ObjectIdentifier -> (none) - ui5-title/ui5-link + ui5-text (compose). Two lines:
title(bold;ui5-linkwhentitleActive, firingtitlePress) andtext(secondary). - sap.ui.core.HTML -> (none) - raw HTML in a (compose).
contentis injected as HTML. Used for (a) custom<style>blocks (CSS classes forclass=attributes - note selectors written against UI5 DOM such as.sapMInputBaseInnerwill not match WC shadow DOM) and (b) small static markup. Must be sanitized/CSP-checked by the renderer (sanitizeContent). - sap.ui.core.Icon -> ui5-icon (adapt).
src="sap-icon://name"->name="name"(icon names are shared with@ui5/webcomponents-icons;sap-icon://tnt/.../businessSuiteInAppSymbols/...->tnt/.../business-suite/...and the matching icon package);size-> CSSfont-size/width/height;color-> CSS colour or semantic (Positive/Negative/Critical/Neutral) ->design;press->mode="Interactive"+click;alt->accessible-name. - sap.m.ObjectNumber -> (none) - composed (compose).
number+unit(unit in smaller text),emphasized-> bold,state-> theming colour var as ObjectStatus,textAlignCSS. Number formatting comes from the binding type, not the control. Not in v1: propertyactive(0/1), propertyinverted(0/1), eventpress(0/1), propertytextAlign(0/1). - sap.tnt.InfoLabel -> ui5-tag (direct).
text-> text content,colorScheme1..10 ->color-scheme,icon-><ui5-icon slot="icon">,displayOnly-> no padding (CSS);design="Set2"style default. Not in v1: propertydisplayOnly(0/2), propertyrenderMode(0/1), propertywidth(0/1). - sap.m.ProgressIndicator -> ui5-progress-indicator (direct).
percentValue->value,displayValue->display-value,showValue=false->hide-value,stateSuccess/Error/Warning/Information ->value-statePositive/Negative/Critical/Information,widthCSS. Not in v1: propertydisplayAnimation(0/2). - sap.m.Image -> (none) -
(compose).
src,width,height,alt,decorative->alt="";densityAwareignored. (ui5-avataronly for avatar-like images.) Not in v1: propertybackgroundPosition(0/1), propertybackgroundRepeat(0/1), propertybackgroundSize(0/1), propertymode(0/2), aggregationdetailBox(0/2), eventpress(0/5), eventerror(0/1), eventload(0/1).
- sap.m.Input -> ui5-input (adapt).
value(two-way: update model onchange, and oninputwhenvalueLiveUpdate=true),placeholder,enabled=false->disabled,editable=false->readonly,typeText/Email/Number/Password/Tel/Url ->type(Url -> URL),maxLength->maxlength,required,showClearIcon->show-clear-icon,valueStateNone/Error/Warning/Success/Information -> None/Negative/Critical/Positive/Information,valueStateText-><div slot="valueStateMessage">,widthCSS.showValueHelp-><ui5-icon slot="icon" name="value-help" mode="Interactive">whose click firesvalueHelpRequest.showSuggestion+suggestionItems(core:Item/ListItem) ->show-suggestions+ui5-suggestion-item text/additional-text.descriptionhas no slot: render aui5-textafter the field. Events:change<-change,liveChange<-input($parameters>/value= current value),submit<- Enter keydown (WC has no submit event;changealso fires on Enter),suggestionItemSelected<-selection-change. Not in v1: propertyfieldWidth(0/3), eventsuggest(0/2), propertyshowTableSuggestionValueHelp(0/3), propertytextFormatMode(0/3), aggregationsuggestionColumns(0/3), aggregationsuggestionRows(0/3), propertyautocomplete(0/2), propertyselectedKey(0/1), aggregationformattedValueStateText(0/1), propertyrequired(0/2), propertyvalueHelpIconSrc(0/1), propertyenableTableAutoPopinMode(0/1). - sap.m.TextArea -> ui5-textarea (direct).
value(two-way;valueLiveUpdateas Input),rows,placeholder,growing,growingMaxLines->growing-max-rows,maxLength->maxlength,showExceededText->show-exceeded-text,editable=false->readonly,valueState,widthCSS;wrappingignored;liveChange<-input. Not in v1: propertycols(0/2). - sap.ui.core.Item -> parent-dependent: ui5-option / ui5-cb-item / ui5-mcb-item / ui5-suggestion-item (adapt). Pure data element:
key->value,text. The tag is chosen by the parent (Select, ComboBox, MultiComboBox, Input suggestions). - sap.m.CheckBox -> ui5-checkbox (direct).
selected(two-way) ->checked,text,enabled=false->disabled,editable=false->readonly,partiallySelected->indeterminate,wrapping->wrapping-type,valueState,required;select<-change($parameters>/selected= checked). Not in v1: propertywidth(0/1). - sap.m.Switch -> ui5-switch (direct).
state(two-way) ->checked,customTextOn/customTextOff->text-on/text-off,type="AcceptReject"->design="Graphical",enabled=false->disabled;change<-change($parameters>/state= checked). - sap.m.SegmentedButton -> ui5-segmented-button (adapt).
selectedKey(two-way) ->selectedon the item whose key matches, written back onselection-change;selectionChange<-selection-change(pass the key, not$parameters>/item+ JS call);widthCSS (items-fit-content). Not in v1: propertycontentMode(0/1). - sap.m.SegmentedButtonItem -> ui5-segmented-button-item (adapt).
text-> text content,icon,key->data-key,enabled=false->disabled,tooltip. - sap.m.Select -> ui5-select + ui5-option (adapt). Items (core:Item / ListItem) ->
<ui5-option value="{key}">{text}</ui5-option>(icon,additionalText->additional-text).selectedKey(two-way) ->valueof the select (orselectedon the matching option); write the chosen option's value back onchange.forceSelection=falsehas no counterpart (WC always selects the first option) - insert an empty option.enabled/editable/valueState/valueStateText/widthas Input.change<-change.$parameters>/selectedItem+.getKey()is UI5 object access - NOT portable; bindselectedKeyinstead. Not in v1: propertyautoAdjustWidth(0/1), propertyicon(0/1), propertytype(0/1), propertywrapItemsText(0/2), propertycolumnRatio(0/1), propertyshowSecondaryValues(0/1), propertytwoColumnSeparator(0/1). - sap.m.DatePicker -> ui5-date-picker (direct).
value(two-way) withvalueFormat->value-formatanddisplayFormat->display-format(same CLDR patterns, e.g.yyyyMMddfor ABAP DATS);placeholder,editable=false->readonly,enabled,required,valueState/valueStateText,widthCSS,minDate/maxDate->min-date/max-date(as strings in value-format).dateValue(JS Date, needs a formatter such as Formatter.DateAbapDateToDateObject) -> convert tovalue.change<-change($parameters>/value,$parameters>/valid). Not in v1: propertyhideInput(0/1). - sap.m.SearchField -> ui5-search-field (fiori) or ui5-input with a search icon (adapt).
value(two-way),placeholder,widthCSS;search<-search($parameters>/query= value;refreshButtonPressed=false),liveChange<-input($parameters>/newValue).ui5-search-fieldis a recent fiori component - check the minimum WC version; theui5-input+<ui5-icon slot="icon" name="search">fallback is safe. Not in v1: propertyenableSuggestions(0/1), aggregationsuggestionItems(0/1). - sap.m.ComboBox -> ui5-combobox + ui5-cb-item (adapt). Items ->
<ui5-cb-item value="{key}" text="{text}" additional-text>;selectedKey(two-way) <->selected-value;value,placeholder,showClearIcon,valueState,widthas Input;change/selectionChange<-change/selection-change.showSecondaryValues-> showadditional-text(WC always shows it when set). Not in v1: propertymaxWidth(0/3), propertyshowSecondaryValues(0/5), propertyfilterSecondaryValues(0/3), eventloadItems(0/1), propertymaxPickerHeight(0/1), aggregationformattedValueStateText(0/1). - sap.m.MultiInput -> ui5-multi-input + ui5-token (adapt).
tokens-> slottokens;showValueHelp->show-value-help-icon,valueHelpRequest<-value-help-trigger;value,placeholder,enabled,width,showSuggestion+suggestionItemsas Input;tokenUpdate<-token-delete($parameters>/type="removed",removedTokens- object access, not portable beyond the token keys). Token add/remove has to be written back into the bound token table by the renderer (UI5 apps use z2ui5.cc.MultiInputExt for that - excluded). Not in v1: propertymaxTokens(0/1), propertyshowTableSuggestionValueHelp(0/1), propertytype(0/1), aggregationsuggestionColumns(0/2), aggregationsuggestionRows(0/2), propertyshowClearIcon(0/1), propertyvalueStateText(0/1), aggregationformattedValueStateText(0/1). - sap.m.Token -> ui5-token (adapt).
text,selected;key-> keep asdata-key;editable=falsehas no per-token attribute (usereadonlyon the multi-input). - sap.m.MultiComboBox -> ui5-multi-combobox + ui5-mcb-item (adapt). Items ->
<ui5-mcb-item value="{key}" text>;selectedKeys(two-way, string array) <->selectedflags of the items (orselected-values);placeholder,width,valueState;selectionChange<-selection-change,selectionFinish<-close. Not in v1: propertyshowSecondaryValues(0/2), propertymaxWidth(0/2), propertyshowSelectAll(0/1), propertyshowClearIcon(0/1), propertymaxPickerHeight(0/1), aggregationformattedValueStateText(0/1). - sap.m.StepInput -> ui5-step-input (direct).
value(two-way),min,max,step,displayValuePrecision->value-precision,enabled/editable/valueState,widthCSS;change<-change($parameters>/value). Not in v1: propertydescription(0/1), propertyfieldWidth(0/1), propertylargerStep(0/1), propertystepMode(0/1), propertytextAlign(0/1), propertyvalidationMode(0/1). - sap.ui.core.ListItem -> as core:Item (+ additional-text, icon) (adapt).
additionalText->additional-text;icon->icon(ui5-optiononly). Not in v1: propertyicon(0/2). - sap.m.DateTimePicker -> ui5-datetime-picker (direct). As DatePicker (
value/valueFormat/displayFormat,dateValuevia conversion). Not in v1: propertyinitialFocusedDateValue(0/1), propertyminutesStep(0/1), propertysecondaryCalendarType(0/1), propertysecondsStep(0/1), propertyshowCurrentDateButton(0/1), propertyshowCurrentTimeButton(0/1), propertyshowTimezone(0/1), propertytimezone(0/1), propertyhideInput(0/1).
- sap.m.Button -> ui5-button (direct).
text-> text content,icon,type->design: Default/Emphasized/Transparent/Attention as is, Accept/Success -> Positive, Reject/Negative -> Negative, Critical -> Attention, Ghost -> Transparent, Back -> Transparent +icon="nav-back", Up ->icon="navigation-up-arrow";enabled=false->disabled,tooltip->tooltip,widthCSS,ariaHasPopup->accessibility-attributes.press<-click. A Button is also the usualopenerof a popover (by id). Not in v1: propertybadgeStyle(0/1). - sap.m.ToggleButton -> ui5-toggle-button (direct).
pressed(two-way),text,icon,type->design,enabled;press<-click($parameters>/pressed= new pressed state).
- sap.m.Column -> ui5-table-header-cell (adapt).
headerchild -> cell content;width->width;hAlignBegin/Center/End/Left/Right ->horizontal-align(also on the column's cells);minScreenWidth/demandPopin/importance->importance+ tableoverflow-mode="Popin"(WC pops in by importance, not by breakpoint);visible=false-> drop the header cell AND that cell of every row;mergeDuplicates-> no counterpart (ignore). Not in v1: propertypopinDisplay(0/7), propertystyleClass(0/1), propertymergeFunctionName(0/1), propertysortIndicator(0/1), propertyvAlign(0/1). - sap.m.ColumnListItem -> ui5-table-row (adapt).
cells->ui5-table-cells;typeActive/Navigation/Detail ->interactive(+navigatedfor Navigation);press<- tablerow-clickdispatched to the clicked row's wire (with that row as context);selected(two-way) <-> selection feature;vAlignCSS;highlight-> no WC attribute (left border CSS). Not in v1: propertynavigated(0/1), aggregationactions(0/1). - sap.m.Table -> ui5-table (+ ui5-table-header-row/-header-cell/-row/-cell, features ui5-table-selection-*, ui5-table-growing) (adapt).
columns-><ui5-table-header-row slot="headerRow">with oneui5-table-header-cellper Column;items(list binding over a client array) -> oneui5-table-rowper entry (row context for relative bindings and${REL}event args), eachcellschild in aui5-table-cell.modeNone/SingleSelect/SingleSelectLeft/SingleSelectMaster/MultiSelect -><ui5-table-selection-single|multi slot="features">; WC selection is a space-separated list ofrow-keys while UI5 bindsColumnListItem.selectedper row: the renderer derivesrow-key(row index) and keeps both in sync.growing/growingThreshold-><ui5-table-growing slot="features" mode="Button|Scroll">with local paging (all rows are already on the client).headerText/headerToolbar/infoToolbar: no slot - render above the table.noDataText->no-data-text,sticky->stickyon the header row,alternateRowColors->alternate-row-colors,widthCSS;inset/popinLayout/fixedLayout/contextualWidthignored.selectionChange<- selection featurechange;itemPress<- tablerow-click. Not in v1: aggregationdragDropConfig(1/1), propertycontextualWidth(0/4), propertyshowSeparators(0/4), propertyshowOverlay(0/1), propertyfixedLayout(0/3), aggregationcontextMenu(0/1), eventpaste(0/1), propertyautoPopinMode(0/2), propertyhiddenInPopin(0/1), eventpopinChanged(0/1), propertyitemActionCount(0/1), propertymultiSelectMode(0/1). - sap.m.List -> ui5-list (adapt).
items(list binding) -> list items;headerText->header-text;headerToolbar-> slotheader;modeNone/SingleSelect/SingleSelectLeft/SingleSelectMaster/MultiSelect/Delete ->selection-modeNone/Single/SingleStart/Single/Multiple/Delete;noDataText->no-data-text;showSeparatorsAll/Inner/None ->separators;growing->growing="Button"+ local paging onload-more.selectionChange<-selection-change(write itemselectedback;$parameters>/listItem+ JS is not portable),itemPress<-item-click,delete<-item-delete. Not in v1: propertybackgroundDesign(0/2), propertyfooterText(0/1), propertygrowingScrollToLoad(0/2), propertyshowUnread(0/1), aggregationcontextMenu(0/1), aggregationswipeContent(0/1), eventswipe(0/1), aggregationinfoToolbar(0/4), propertysticky(0/1), propertyenableBusyIndicator(0/5), propertygrowingDirection(0/1), propertygrowingTriggerText(0/1). - sap.m.StandardListItem -> ui5-li (direct).
title->text,description,icon(sap-icon://x ->icon="x"; an image URL -><img slot="image">),info->additional-text,infoState->additional-text-state(Success->Positive, …),highlight->highlight,typeInactive/Active/Navigation/Detail/DetailAndActive ->type(Inactive/Active/Navigation/Detail),selected(two-way),wrapping->wrapping-type="Normal",counter-> append toadditional-text;press<-click,detailPress<-detail-click. Not in v1: propertyunread(0/1), propertyadaptTitleSize(0/2), aggregationavatar(0/1), propertyinfoStateInverted(0/2), propertyinfoIcon(0/1), propertywrapCharLimit(0/1), propertynavigated(0/1). - sap.m.CustomListItem -> ui5-li-custom (direct). Content -> default slot;
type,selected,highlightas StandardListItem;press<-click. - sap.m.Tree -> ui5-tree (adapt).
items="{/T_NODES}"binds a NESTED client array (UI5 JSONModel tree binding: every array-valued property of a node is its children) - the renderer recurses and emits nestedui5-tree-items.headerText->header-text,mode->selection-mode,headerToolbar-> slotheader;toggleOpenState<-item-toggle. Not in v1: aggregationdragDropConfig(1/1), aggregationcontextMenu(0/1), propertyincludeItemInSelection(0/1), aggregationinfoToolbar(0/1). - sap.m.StandardTreeItem -> ui5-tree-item (direct).
title->text,icon,selected,expanded(UI5 keeps expansion in the binding; default collapsed).
- sap.m.Dialog -> ui5-dialog (adapt). Shown via
client->popup_display( )(slot POPUP) -> render and setopen;popup_destroy( )/ action POPUP_CLOSE -> close + remove.title->header-text,icon-> customheaderslot,stateError/Warning/Success/Information ->stateNegative/Critical/Positive/Information,contentWidth/contentHeight-> CSS width/height of the content wrapper,resizable,draggable,stretch;buttons/beginButton/endButton/footer-><ui5-bar slot="footer">endContent (begin before end);customHeader/subHeader-> slotheader;showHeader=false-> empty header;verticalScrolling/horizontalScrollingCSS overflow.afterClose<-close(Escape closes a WC dialog client-side: the renderer must fire theafterClosewire, or cancelbefore-closewhen none is wired, so the server popup state does not drift). Not in v1: propertyshowFullScreenButton(0/1). - sap.m.Popover -> ui5-popover (adapt). Shown via
client->popover_display( xml, by_id )->opener= the DOM id of the control with that view id,open=true; POPOVER_CLOSE /popover_destroy( )-> close.title->header-text(showHeader=false-> none),placementTop/Bottom/Left/Right/Auto/PreferredTopOrFlip… ->placementTop/Bottom/Start/End (Auto -> End),contentWidth/contentHeightCSS,footer-> slotfooter,modal;afterClose<-close. Not in v1: eventafterOpen(0/1), propertyresizable(0/1), propertyverticalScrolling(0/1), aggregationcustomHeader(0/1), propertycontentMinWidth(0/1).
- sap.m.MessageStrip -> ui5-message-strip (direct).
text-> text content;typeInformation/Success/Warning/Error/None ->designInformation/Positive/Critical/Negative/Information(+hide-icon);showIcon=false(UI5 default false!) ->hide-icon; UI5 has NO close button by default, WC does: sethide-close-buttonunlessshowCloseButton=true;close<-close.enableFormattedText-> limited HTML (a, b, i, strong, em, br, code) in the text. Not in v1: aggregationlink(0/1), aggregationcontrols(0/1), propertycolorScheme(0/1).
- sap.ui.core.CustomData -> none - data-* attribute (compose).
writeToDom=true->data-{key}="{value}"on the parent element, otherwise drop. ($event.getSource().data(...)readers are not portable.) - sap.m.FlexItemData -> none - CSS on the child (compose).
growFactor->flex-grow,shrinkFactor->flex-shrink,baseSize->flex-basis,alignSelf,maxWidth. Safe to drop. Not in v1: propertystyleClass(0/5), propertyorder(0/1), propertybackgroundDesign(0/5), propertymaxWidth(0/5). - sap.ui.layout.GridData -> none - CSS on the child (compose).
span="XL6 L6 M12 S12"/spanL…->grid-column: span nper breakpoint,linebreak*->grid-column-start:1,indent*-> start offset. Safe to drop. Not in v1: propertyindent(0/2), propertyindentL(0/2), propertyindentXL(0/1), propertylinebreakM(0/2), propertyspanL(0/1), propertyspanM(0/1), propertyspanS(0/1), propertyspanXL(0/1), propertyvisibleL(0/1), propertyvisibleM(0/2), propertyvisibleS(0/2), propertyvisibleXL(0/1). - sap.m.OverflowToolbarLayoutData -> overflow-priority on the toolbar item (adapt).
priorityNeverOverflow/AlwaysOverflow/High/Low ->overflow-priority(Default for High/Low). Safe to drop. Not in v1: propertygroup(0/5), propertyminWidth(0/3), propertyshrinkable(0/6), propertycloseOverflowOnInteraction(0/1), propertymaxWidth(0/2).