#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.
An imperative method needs no JavaScript at all. The client can call one on a control by id:
" 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.