App State, Share, Bookmark ​
A link that restores an app exactly as it stands — every value the user has
typed, the row they selected, the tab they opened — not just the app it was.
That is the app state, and it is the same thing a standard UI5 app does with
sap-xapp-state: client->app_state_set_active( ) puts the id of the current
state in the URL, and it is advanced on every roundtrip.
METHOD z2ui5_if_app~main.
IF client->check_on_navigated( ).
client->app_state_set_active( ).
view_display( ).
ENDIF.
ENDMETHOD.
From then on the URL carries the id of the current state, and a reload, a
bookmark, or that URL opened in another tab or on another device comes back to
this app with that state — for the same user: a draft belongs to the user who
created it, so the URL in somebody else's browser starts the app fresh.
client->app_state_set_active( abap_false ) switches the URL tracking off
again.
An example URL:
.../sap/bc/z2ui5?sap-client=001&app_start=z2ui5_cl_smp_app_004#/z2ui5-xapp-state=024251849E5A1EDFB1DAE2C97C8CE8C2
Nothing extra is stored for this. The draft the framework already persists
between two roundtrips — the same one
Statefulness describes — is the state
container; the app state only puts its id in the URL, where a browser can keep
it. The hash value is a server-side key pointing at that draft, so the cost is
a hash that changes, and the limit is the draft's own lifetime: once it expires
(draft_exp_time_in_hours in the
User Exits, four hours by default), the
link no longer restores anything.
A Complete App ​
CLASS z2ui5_cl_sample_app_state DEFINITION PUBLIC.
PUBLIC SECTION.
INTERFACES z2ui5_if_app.
DATA mv_quantity TYPE string.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS z2ui5_cl_sample_app_state IMPLEMENTATION.
METHOD z2ui5_if_app~main.
IF client->check_on_navigated( ).
DATA(view) = z2ui5_cl_ui5_view_builder=>factory(
)->ele( n = `View` ns = `mvc`
)->a( n = `xmlns` v = `sap.m`
)->a( n = `xmlns:mvc` v = `sap.ui.core.mvc`
)->ele( `Page`
)->tag( `Label`
)->a( n = `text` v = `quantity`
)->tag( `Input`
)->a( n = `value` v = client->_bind( mv_quantity )
)->tag( `Button`
)->a( n = `text` v = `post with state`
)->a( n = `press` v = client->_event( `BUTTON_POST` ) ).
client->view_display( view->stringify( ) ).
ENDIF.
CASE client->get( )-event.
WHEN `BUTTON_POST`.
client->message_toast_display( `data updated and url adjusted` ).
client->app_state_set_active( ).
ENDCASE.
ENDMETHOD.
ENDCLASS.
Type something, press the button, and watch the address bar: the id in the hash advances with every roundtrip, and each one restores what was on screen when it was written.
Getting the Link ​
client->app_state_get_href( ) returns the absolute link to the current state,
composed in the backend. The app owns that string, so it can do anything with
it — copy it, show it in an Input the user can select, mail it, render it as
a QR code:
CLASS z2ui5_cl_sample_share DEFINITION PUBLIC.
PUBLIC SECTION.
INTERFACES z2ui5_if_app.
DATA mv_quantity TYPE string.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS z2ui5_cl_sample_share IMPLEMENTATION.
METHOD z2ui5_if_app~main.
CASE abap_true.
WHEN client->check_on_navigated( ).
DATA(view) = z2ui5_cl_ui5_view_builder=>factory(
)->ele( n = `View` ns = `mvc`
)->a( n = `xmlns` v = `sap.m`
)->a( n = `xmlns:mvc` v = `sap.ui.core.mvc`
)->ele( `Shell`
)->ele( `Page`
)->tag( `Label`
)->a( n = `text` v = `quantity`
)->tag( `Input`
)->a( n = `value` v = client->_bind( mv_quantity )
)->tag( `Button`
)->a( n = `text` v = `share`
)->a( n = `press` v = client->_event( `BUTTON_POST` ) ).
client->view_display( view->stringify( ) ).
WHEN client->check_on_event( `BUTTON_POST` ).
client->follow_up_action( val = z2ui5_if_client=>cs_event-clipboard_copy
t_arg = VALUE #( ( client->app_state_get_href( ) ) ) ).
client->message_toast_display( `clipboard copied` ).
ENDCASE.
ENDMETHOD.
ENDCLASS.
The link is launchpad-safe: the shell hash of the page survives in it, so opened from a Fiori Launchpad it lands in this app with this state instead of on the launchpad home page.
It costs a roundtrip, and that is usually what you want
app_state_get_href( ) is a backend method, so a Share button that calls it
is a normal event. That is the useful shape: whatever has to be saved before
the link is worth sharing is saved in the same roundtrip, and the composed link
can be shown as well as copied.
What the Link Restores ​
The browser sends the state id back with its first request, and the framework loads the app from that draft. The screen comes back as it was — the same input values, the same selection — because that is what the draft holds.
Only for the user the draft belongs to, though. The framework binds every draft to its owner, and another user opening the link gets the app started fresh, exactly as if the draft had expired — a leaked link shows nobody else the screen.
What it does not carry is anything the app read from outside itself. A
SELECT runs again on the restore, so a list is refreshed rather than frozen,
and authorizations are checked as they stand now: an app-state link is a link
to a screen, not a copy of the data on it.
A restored state enters through check_on_navigated
Opening an app-state link loads the app from its draft and runs main( ) with
client->check_on_navigated( ) true — check_on_init( ) stays false, because
the instance already existed when the link was made. Display the view in that
branch, or the link opens to whatever the browser was showing before.
check_on_navigated( ) covers the first start as well, so it is the complete
display condition on its own. Same rule as everywhere else:
Life Cycle.
It claims the app hash
The app state writes the URL, and so do framework routing and an app that owns its own hash — all three want the same string. Use one of them per app; see Hash.
Bookmarking ​
The same URL works as a bookmark, with the same limit: the server keeps the
draft behind it for a configurable time, four hours by default. A bookmark
older than that opens the app, not the state — see the
draft service
source and the draft_exp_time_in_hours
user exit.
App State or a Route? ​
They answer different questions, and the difference is what the link restores:
| restores | |
|---|---|
Hash, routing mode fresh |
the app, started clean |
Hash, routing mode keep |
the app on the stack, as the user left it |
| Hash, app-owned | the screen inside the app the hash names |
| App state | the exact roundtrip — this app, this input, this selection |
Routing is about where the user is and follows the app stack. The app state is about what is on the screen, and is the one to reach for when a link has to bring the user back to the same thing — after a reload, from a bookmark, on another device.
Working Samples ​
Complete apps from the sample catalog
that use what this page describes. Each is a single class in abap2UI5/samples
unless its row names another of the three sample repositories — pull that repository with
abapGit and start the class with ?app_start=<class>.
| Sample | Class |
|---|---|
| App State, Bookmark and Share (A) | Z2UI5_CL_SMP_APP_498 |