Skip to content

View Builder

Instead of maintaining UI5 views as XML files, you assemble them in JavaScript — with a fluent builder that produces the XML in the background. The output is always a <mvc:View> XML string that goes to the frontend.

The simplest case

js
const z2ui5_cl_xml_view = require("abap2UI5/z2ui5_cl_xml_view");

const view = z2ui5_cl_xml_view.factory()
  .Shell()
  .Page({ title: "Hello" })
  .Input({ value: "world" });

client.view_display(view.stringify());

factory() returns a new view. Each method creates a UI5 control under the current node and returns the new node — that's how you naturally chain the tree:

js
view
  .Page()                  // ← new node
    .Input()               // ← child of Page, new node
    .Button();             // ← child of Page (siblings via auto-insertion)

Most builder methods set the target to the just-created control as a container. When you explicitly need an aggregation slot (e.g. content, items, cells), there are methods with a lowercase initial:

js
view
  .SimpleForm({ editable: true })
    .content()                       // ← opens the <SimpleForm.content> aggregation
      .Label({ text: "Name" })
      .Input({ value: "..." });

Important aggregation methods

MethodAggregation slot
.content()<…:content> (Page, SimpleForm, Panel, …)
.items()<…:items> (Table, List, ComboBox, …)
.columns()<…:columns> (Table)
.cells()<…:cells> (ColumnListItem)
.headerContent()Page toolbar
.footer()Page footer
.endButton()Dialog

They are lowercase to distinguish them from the control methods (PascalCase).

Two method styles

Besides the PascalCase methods used in these docs, the builder also offers lowercase, abap2UI5-style methods (.shell().page().input(...)) — the transpiled sample apps in core/srv/app/samples/ use that style, since it maps 1:1 to the ABAP originals. Both styles produce the same XML; pick whichever reads better to you.

Common controls

js
view.Page({ title: "..." });
view.Title({ text: "..." });
view.Label({ text: "..." });
view.Input({ value: "..." });
view.Button({ text: "...", press: client._event("EVT") });
view.Text({ text: "..." });
view.CheckBox({ selected: ..., text: "..." });
view.ComboBox({ selectedKey: ..., items: ... });
view.DatePicker({ value: ... });
view.DateTimePicker({ value: ... });
view.TimePicker({ value: ... });
view.Switch({ state: ... });

view.Table({ items: ... }).columns().Column().Text({ text: "Col" });
view.List({ items: ... }).StandardListItem({ title: "...", description: "..." });
view.SimpleForm({ editable: true });
view.Grid({ defaultSpan: "L6 M12 S12" });
view.HBox({ ... });
view.VBox({ ... });

view.MessageStrip({ text: "...", type: "Information" });
view.IconTabBar({ ... });
view.Wizard({ ... });

Practically everything UI5 provides in sap.m / sap.ui.layout / sap.tnt is covered — methods map 1:1 to control names, properties to attributes. Boolean values are converted automatically to "true"/"false".

Values: raw, bound, or expression

js
view.Input({ value: "Hello" });                            // literal string
view.Input({ value: client._bind_edit(this.name) });       // two-way bind: {/XX/name}
view.Input({ value: client._bind(this.name) });            // one-way bind: {/name}
view.Input({ value: `{= ${client._bind(this.name)} }` });  // expression binding
view.Input({ value: `{path: '/name', formatter: '.fmt'}` });// classical binding

Whatever you pass as a string lands 1:1 in the XML attribute. The bind helpers are pure string builders.

Custom controls (z2ui5 namespace)

Via view._z2ui5() you get the custom control decorator (see z2ui5_cl_xml_view_cc.js):

js
view.Page()
  ._z2ui5().geolocation({
    finished:  client._event("GEO_DONE"),
    longitude: client._bind_edit(this.lng),
    latitude:  client._bind_edit(this.lat),
  });

Available custom controls (selection):

  • camera_picture, camera_selector — camera access
  • chartjs — Chart.js integration
  • file_uploader — file upload
  • geolocation — GPS
  • bwip_js — barcode generator
  • info_frontend — UI5 version, device info
  • scrolling, timer, websocket, storage
  • spreadsheet_export — Excel export
  • multiinput_ext, smartmultiinput_ext — extended MultiInputs

All docs: core/srv/z2ui5/02/z2ui5_cl_xml_view_cc.js.

Embedding static XML

If you already have a view as XML (e.g. exported from a designer), simply bypass the builder:

js
const fs = require("fs");
const path = require("path");

const xml = fs.readFileSync(path.join(__dirname, "MyView.view.xml"), "utf8");
client.view_display(xml);

The roundtrip works exactly the same way — the frontend renderer doesn't care how the XML was produced.

→ Example: Static XML View.

Factories for special views

js
z2ui5_cl_xml_view.factory();          // normal view (with Shell+Page)
z2ui5_cl_xml_view.factory_popup();    // view for dialog/popup

Popups go through client.popup_display(view.stringify()) instead of view_display(...). → More in Popups & Toasts.

Two nested views (master-detail)

A pattern for classic master-detail layouts:

js
client.view_display(masterView.stringify());
client.nest_view_display(detailView.stringify(), "containerId", "addItem");

nest_view_display injects a second view via JS insert into a specific container of the main view. There are two nesting levels (nest_view_display, nest2_view_display) for deeper layouts.

→ Continue with Data Binding.

Released under the MIT License.