App State ​
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 pasted into somebody else's browser comes back to this
app with that state. 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.
Handing the Link to Somebody ​
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 a recipient opening it from a Fiori Launchpad 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 recipient's browser sends the state id back with its first request, and the framework loads the app from that draft. They see the screen the sender saw — the same input values, the same selection — because that is what the draft holds.
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 the recipient's own: an app-state link is a link to a
screen, not a copy of the data on it, and it grants nothing the recipient did
not already have.
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 is meant to be handed to somebody who has to see the same thing.
Working Samples ​
Complete apps from the sample catalog
that use what this page describes. Each is a single class — pull the repository with
abapGit and start it with ?app_start=<class>.
| Sample | Class |
|---|---|
| App State, Bookmark and Share | Z2UI5_CL_SMP_APP_498 |