abap2UI5
Version 1.147.0

#12 Where Your Own JavaScript Goes ​

Sooner or later an app needs something the XML view cannot express. A chart library. A control nobody has wrapped. A UI5 method that exists only as a method — sap.m.Carousel moves through setActivePage( ) and through nothing else, and no property will do it for you.

This is the moment where frameworks usually grow a plugin system, and then a plugin registry, and then a page of documentation about lifecycle hooks. abap2UI5 has none of that, deliberately. It has three seams, each one a declared place rather than an escape hatch.

Three seams, from the cheapest to the widest: a method call by control id, an expression in the view, a custom control in its own BSP.

Three seams, from the cheapest to the widest: a method call by control id, an expression in the view, a custom control in its own BSP.

An imperative method needs no JavaScript at all. The client can call one on a control by id:

abap
    " t_arg is positional: control id, method, parameters
    client->follow_up_action( val   = z2ui5_if_client=>cs_event-control_by_id
                              t_arg = VALUE #( ( `myCarousel` )
                                               ( `setActivePage` )
                                               ( `page2` ) ) ).

Any public method of the control is reachable, unless the frontend's denylist refuses it — destroy, the bind… and attach… families, the generic setAggregation and its kin. A short list of methods also declares the kind of each argument: setActivePage is on it, which is why page2 arrives as the page with that id rather than as a string, and an argument beyond what an entry declares is dropped in silence — a debugging session you can skip by reading that list first.

A custom control lives in its own BSP. The frontend resolves two reserved resource roots — z2ui5_cci for the custom-controls addon, z2ui5_ccc for a customer's own extension — so a control loads through the UI5 loader like any other module, not as a string smuggled through a view.

A view attribute can compute. UI5 expression binding is available in an app view — {= ${STATUS} === 'E' ? 'Error' : 'None' } — evaluated in the browser against the model that just arrived, with no roundtrip and no module to load. Write it as a backtick literal rather than a string template: a template has to escape every brace, and one missed escape is a parser error on the whole statement instead of a wrong string. Ask how we know.

Everything else is a system decision, not an app decision. Frontend code of your own is a custom control in the customer frontend BSP (z2ui5_ccc), and what the initial page loads is the bootstrap the user exit sets through z2ui5_if_ui5_exit — one place, reviewable, and the same for every app in the system.

None of them lets an app change the framework, and none requires the framework to change for an app. No plugin registry to learn, and no pull request to wait for either.

Extensibility is not the absence of a boundary. It is knowing exactly where the boundary is.

Edit this page on GitHub ↗ Last updated: