0% found this document useful (0 votes)
1K views

Restoring Fiori Application State - SAP Blogs

Uploaded by

Burak Karakaş
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1K views

Restoring Fiori Application State - SAP Blogs

Uploaded by

Burak Karakaş
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 16

Follow RSS feed Like

Community

Ask a Question Write a Blog Post Login

John Patterson
June 19, 2017 3 minute read

Restoring Fiori Application State


13 Likes 9,423 Views 22 Comments

When doing cross application navigation in Fiori, that is navigating between applications. On return, rather
than picking up from where you left o , a new instance of the application is created. Meaning the app is in an
initial state and not in the state when you left it. To solve this we need to persist the state between calls.
Store any lters, search options, interactions the user has applied, then reapply them on return.

There has not been a documented standard approach for solving this. As a result we see and hear many
di erent ways UI5 developers are solving this by themselves. If you study some of the standard SAP
applications, there is an approach for managing state using existing Fiori services. In this blog I will highlight
how it works, providing an easy way to do it yourself using generic reusable SAP code.
Follow RSS feed Like

In the video above we see a variety of di erent lters being applied to a work list. We then see navigation to a
second application. On return all those lters and interactions are reapplied.
Behind the scenes
Prior to navigation the application state is persisted on the server.

We can see below that the API /UI2/INTEROP/GlobalContainers is called and values are posted to the
Layered Repository (LRep) table /uif/lrepdcontcd on the Gateway server.

The key for retrieving this data is added as a parameter to the URL.

On return the key is read from the URL, the data is retrieved and the app state is restored.
Because the data is persisted on the server, you can bookmark the URL, reopen in a browser and restore the
state of the application. You can share bookmarks between di erent makes of browsers and di erent users.
However the state key is recreated each time the data is loaded.
Follow RSS feed Like
How does it work?
1. Prior to navigation save the app state

// create a new Application state (oAppState)


oAppState for this Application instance
oAppState = sap.ushell.Container
.getService("CrossApplicationNavigation")
.createEmptyAppState(this);
oAppState.setData(oStateToSave); // object of values needed to be restored
oAppState.save();

2. Update the URL hash with the key

var oHashChanger = sap.ui.core.routing.HashChanger.getInstance();


var sOldHash = oHashChanger.getHash();
var sNewHash = sOldHash + "?" + "sap-iapp-state=" + this.oAppState.getKey();
oHashChanger.replaceHash(sNewHash);

3. Navigate to another Fiori application

sap.ushell.Container
.getService("CrossApplicationNavigation")
.toExternal({
target: {
semanticObject: sSemanticObject,
action: sAction
},
params: oParams,
appStateKey : oAppState.getKey()
});

4. On return read the key from the URL, retrieve the data and restore the app

var sHash = oHashChanger.getHash()


var sAppStateKey = /(?:sap-iapp-state=)([^&=]+)/.exec(sHash)[1];

sap.ushell.Container
.getService("CrossApplicationNavigation")
.getAppState(sAppStateKey)
.done(function (oSavedAppState) {
<< code for restoring app state >>
});
Things you need to consider doing it this way, AppState instances are immutable, means the key will
Follow RSS feed Like
change, the URL may include routing and parameters in the hash.

Alternative Approach
The last couple of months I have been helping customers investigate and adopt the ABAP Programming
Model for SAP Fiori, in preparation for thier S/4 HANA transformation. Part of this has been Developing
Apps with SAP Fiori Elements. Fiori Elements uses the sap.ui.generic.app library, which has a very easy to
reuse standalone NavigationHandler which abstracts away a lot of the complexity.

NOTE: This option is only available on SDK version 1.36.X and higher. There are other alternatives which
work like sap/suite/ui/generic/template/ListReport/nav/NavigationHandler on 1.34 and below.

To implement

1. Import the Navigation handler into your controller

sap.ui.define([
..
"sap/ui/generic/app/navigation/service/NavigationHandler",
"sap/ui/generic/app/navigation/service/NavType"
], function(.. NavigationHandler, NavType) {

2. Instantiate the navigation handler and provide a callback for after navigation

onInit: function() {
..
// create an instance of the navigation handler
this.oNavigationHandler = new NavigationHandler(this);

// on back navigation, the previous app state is returned in a Promise


this.oNavigationHandler
.parseNavigation()
.done(this.onNavigationDone.bind(this));

// the app state which needs persisting


this._oAppState = {
selectedTabFilter: "all",
searchText: "",
selectedContextPaths: [],
selectedCategories: [],
selectedSuppliers: []
};
3. Do the cross app navigation
Follow RSS feed Like

onPress: function(oEvent) {
.
//(sSemanticObject, sActionName, vParameters?, oAppData?, fnError?)
this.oNavigationHandler
.navigate("Navigation", "sample",{},{ customData: this._oAppState });

4. Restore the application state

/**
* if navigated back with appstate enabled then rehydrate the page using the
* stored data
* @param {Object} oAppData data persisted via iAppState
* @param {Object} oURLParameters paramters passed in
* @param {String} sNavType type of navigation
*/
onNavigationDone: function(oAppData, oURLParameters, sNavType) {
switch (sNavType) {
case NavType.initial:
break;
case NavType.iAppState:
this._oAppState = oAppData.customData;
// set the previously selected icon filter tab
this.byId("iconTabBar").setSelectedKey(oAppState.selectedTabFilter);

// apply previous filters to table


this._applyFilters();

// set the previous search state


this.byId("searchField").setValue(oAppState.searchText);

// set the previously selected multi combo tokens


this.byId("categories").setSelectedKeys(oAppState.selectedCategories);
this.byId("suppliers").setSelectedKeys(oAppState.selectedSuppliers);

// select previously selected rows


this.byId("table")
.setSelectedContextPaths(oAppState.selectedContextPaths);
break;
}

Want More?
Demo Application in video

Source Code for Demo Application


Not on S/4 Hana yet or want to know more about the “ABAP Programming Model for SAP Fiori” a
Follow RSS feed Like
best practice for rapidly building meta-driven SAP Fiori apps on top of ABAP OData Services?

Come to my session at SAP TECHED Las Vegas

Ten tips from Using the ABAP Programming Model for SAP Fiori on AnyDB

Alert Moderator

Assigned tags

SAP Fiori | SAP Mentors | SAPUI5 |

Related Blog Posts

Learn Functional Side Backend Con guration for My spend Fiori Application Step by Step – (D)……..:)
By Former Member , Feb 15, 2015

Learn Backend Business Con guration for My spend Fiori Application Step by Step – (C)……..:)
By Former Member , Feb 15, 2015

You’ve accessed the Extended SAP Fiori Demo Cloud Edition…Now What?
By Liz Cawley , May 07, 2015

Related Questions

Fiori Cross app navigation - Keep source app alive


By Yogesh Beria , Dec 27, 2017

Where should SAP Fiori be installed?


By Former Member , May 13, 2015

My Inbox app : Issue in release task


By MEGHAL SHAH , Feb 18, 2016

22 Comments
You must be Logged on to comment or reply to a post.
Follow RSS feed Like

Simon Kemp

June 19, 2017 at 8:16 am

Great stu . Thanks for sharing your knowledge on this topic John.

Like (1)

Mike Doyle

June 19, 2017 at 11:06 am

Great blog as always, John.  I hadn’t come across NavigationHandler before, and it looks very interesting.

Regarding the rst method, am I right in thinking that the replaceHash method will trigger events in the
router, such as onRouteMatched?  That’s not really want we want in this case, is it?

Like (0)

John Patterson | Post author

June 19, 2017 at 12:16 pm

Hi Mike

Thanks,

AFAICS a Fiori hash is made up of multiple parts,

shellhash /  intent / appSpec cRoute / params etc.

i have a feeling param changes are ignored and (route) events are red for app-speci c parts only

you would have to debug  sap.ushell.services.ShellNavigationHashChanger to see what really happens

JSP

Like (0)

John Patterson | Post author

June 19, 2017 at 12:50 pm


I just debugged
Follow RSS feed Like

sap.ui.core.routing.HashChanger.getInstance() returns

sap.ushell.services.ShellNavigationHashChanger when u run in FLP

sap.ushell.services.ShellNavigationHashChanger.prototype.replaceHash – doesnt replace the browser


history, therefore no route change, I debugged to con rm

JSP

Like (0)

Jiawei Cao

February 12, 2020 at 2:51 pm

Hi John,

both ShellNavigationHashChanger and sap.ui.core.routing.HashChanger modify the browser hash but don’t
create the new history entry in the browser once the replaceHash method is called. The same route is
matched again after only appending the sap-iapp-state id is appended to the hash. Therefore there’s no UI
change made since the matched route isn’t changed. However, the pattern of the route needs to be able to
handle this optional query parameter and de ne “:?sapiappstate:” in the route’s pattern where an inner-app
state can be appended.

Could you please verify whether the routes in your app have the optional query parameter?

Best regards,

Jiawei

Like (0)

Phil Cooley

June 19, 2017 at 11:53 am

Nice John. De nitely an interesting topic and a nice easy explanation on how this can be achieved.  Thanks!

Like (1)

Nabi Zamani

June 19, 2017 at 12:11 pm

Pretty cool blog, John! After the Navigation & Routing tutorial I thought about publishing something like
“Fiori Cross App Navigation” which should include app states as well. With this great blog it might be
obsolete now… Thanks for sharing!
Follow RSS feed Like
Like (0)

John Patterson | Post author

June 19, 2017 at 12:29 pm

Hi Nabi

Mate please do publish, in my case by writing the blog I have signi cantly increased my understanding, if
others do likewise we can ll more gaps.

Cheers

JSP

Like (1)

Former Member

June 20, 2017 at 5:50 am

This is nice, works similar to the Saved searches option in FPM etc..

If you want to store data across applications, you can simply store it on the Window, so in this case you can
store the Search Filters as an object and also the search results on the Window as a JS object (JSON)

Simply write “window.myName = ‘Sai’ ” and it should persist in the same browser session. SAP stores all its
framework objects this way.. See pic.

Like (0)

Former Member

June 20, 2017 at 5:51 am


Follow RSS feed Like

Like (0)

Former Member

June 21, 2017 at 8:48 pm

hi John,

Good article. I’d like to hear your thoughts about storing client state in the server.. isn’t this exactly the
problem we tried to solve using stateless apps? – As far I can see (in fact, as far the payload is concerned) a
“session” is sort of created and you chunk the session reference in the URL, not too di erent from a
jsessionid.

I understand limitations that a URL may have, but why not qs the same payload into the URL and relieve the
server from a request while also removing all the issues the same approach used by SAP will cause?

Because now you’ve bound the access URL to a session, the session must remain “in nite” in the server…
that table which saves each JSON can never be deleted anymore neither cleared, and if it is, then you broke
your resource locator and you made a valid resource become an invalid resource.

I’d also suggest you add a version identi er so when you modify applications and later on a bookmarked
resource comes back in, you can fail gracefully – not always necessary but often good to keep track.

 
Would like to understand how many times have you faced the limit of 2048 when dropping state into
parameters? Follow RSS feed Like

Cheers,
Dan.

Like (0)

John Patterson | Post author

June 22, 2017 at 1:30 am

Hi Dan

Thanks

This is a standard SAP approach, as much as I like writing code, I would rather reuse other peoples.

The appstate is persisted to the back end, however it is not retrieved from the back end if found in the FLP
session memory.

I am in two minds about the backend state persistence, but can see some wins for users.

There are standard jobs for purging LRep data. One of many jobs for Fiori cache and data management.

If you debug the sample application provided you will see it uses Local Storage, it delegates to Fiori
Personalization service, which supports Session, Local Storage, Server side caching and DB options.

I have faced the URL limitation a few times, not with this technique though.

Cheers
JSP

Like (0)

Tom Van Doorslaer


June 27, 2017 at 7:40 am
Follow RSS feed Like
But wait, there’s more!

You can also pass an appstate to your navigation target:

var oNav = sap.ushell.Container.getService("CrossApplicationNavigation");


oNav.toExternal({ target: { shellHash: sIntent + "?sap-xapp-state=" + encodeURIComponent(JSON.stri

(example:
sIntent: "#Notificaton",
sAction: "Create",
oJson: {type:"D1", text:"a really long text here", image="data:image/png,base64...." }
)

This allows you to pass large JSON objects to your target, rather than just an ID.

Example: you want to create a follow on document, which contains the entire text from the original
document. A large text cannot be passed via the URL… so you add the text into a json object

{ text: sText}

and you pass it as an x-app-state. This saves the object and generates a key.

In the target app, you load your app state (ui5 will automatically use the key from the url) and hey, presto!
you now have access to the json object.

Edit: Completely missed the ball here. We have a rede nition of the navigation handler which automatically
transforms any URL parameters into an appState in the local storage….

Like (1)

Vladislav Volodin

August 14, 2017 at 12:11 pm

You know about the maximum URI length limitation, don’t you? I wouldn’t use the poor URI to store as a
storage for strange objects.

Like (0)

Tom Van Doorslaer

October 4, 2017 at 12:23 pm


Didn’t I say that we store the “big” object in the local state and only pass the identi er of the local state
Follow RSS feed Like
through URL?

I thought I did…

Like (0)

Krishna Kishor Kammaje

August 20, 2018 at 6:35 am

I have expanded a little on sap-xapp-state here. If anyone is interested.  OVP-Navigation

Like (0)

Anmol Goel

July 2, 2018 at 10:03 am

Hi John,

Do you know for how long does it persist the app state in the table?

Regards,

Anmol

Like (0)

Tobias Schnur

November 22, 2018 at 3:02 pm

Hello,

thanks for the great blog. I actually think there is a big disadvantage of the generic Navigation Handler. It can
only navigate based on the intent (object + action). It is not possible to provide any additional hash to trigger
an inner app navigation in the target app in case you do not want to navigate to the start page of the target
app.

However I think it’s possible to use method “storeInnerAppState” of the navigation handler instead:

_storeState: function () {
this._oAppState.selectionVariant = this._oSmartFilterBar.getDataSuiteFormat(true);
this._oAppState.tableVariantId = this._oSmartTable.getCurrentVariantId();
this._oNavigationHandler.storeInnerAppState(this._oAppState);
Follow RSS feed Like
}

and trigger the navigation “manually:

if (this._oIsNavSupported) {
this._oIsNavSupported.done(jQuery.proxy(function (aIntentSupported) {
if (aIntentSupported[0].supported) {
this._storeState();

oCrossApp.toExternal({
target: {
semanticObject: "ServiceOrder",
action: "manage"
},
appSpecificRoute: "&/HeaderSet/" + sSrvOrderGuid
});
}
}, this));
}

The “sap-iapp-state” is added to the URL:

“/sap/bc/ui5_ui5/ui2/ushell/shells/abap/FioriLaunchpad.html?sap-client=100&sap-
language=EN#Shipment-display&/?sap-iapp-
state=ASJKBG22X5TO0I1Q6ANGB6C5HCL95RFQCMP6DMQG”

However when I navigate back from the target it does not work. It seems that there is no matching route to
this hash. I haven’t found the exact issue yet. The Component.js is loaded but no view is loaded.Someone
has an idea? Is the syntax used in the URL above not correct?

Regards

Tobias

Like (0)

Jiawei Cao

February 12, 2020 at 2:40 pm


Hi Tobias, Follow RSS feed Like

I am from the SAPUI5 Core Framework team where the modules under sap.ui.core.routing are maintained. I
came across this blogpost through a bug report and the issue which is reported there is the same one as
what you wrote.

Once the inner-app state is used in one application, all of the routes where an inner-app state id can be
appended need to de ne an optional query parameter in their pattern to make the hash that has an inner-
app state id in it can still match the route and not lead to the “bypassed” event in UI5 routing. Suppose you
have a route with an empty string pattern “”, the pattern needs to be changed to “:?sapiappstate:” (the
query parameter can have any arbitrary name) in order to let the route be matched after the inner-app state
is appended to the hash.

Best regards,

Jiawei

Like (0)

Ekansh Saxena

February 20, 2020 at 8:30 am

Hi Jiawei Cao ,

I am on version 1.60.6 and found that ‘getDataSuiteFormat’ function is deprecated and I should use
getUiState function instead. Now I use this getUiState() and save the UiState in app state. When I navigate
back to my source app and retrieve the UiState from the app state data, I try to use function setUiState to
set the lter data in smart lter bar. It gives error that it couldn’t nd method getSelectionVariant from the
UiState data that I passed since it is a shallow copy of data returned from getUiState() thus doesn’t have
any methods.

Am I doing something wrong here or is it a bug?

BR, Ekansh

Like (0)

Melvin Poinoosawmy

January 28, 2019 at 4:46 pm

Hello,

Do you have any idea how to preserve the state of the column of Smart table ?

Lets assume we reverse the Supplier and the Price Column, how can we store the order and the visibility of
columns ?
 
Follow RSS feed Like

Best regards

Melvin

Like (1)

Jan Mattfeld

May 13, 2019 at 11:53 am

You could read the UIState of your SmartTable [1] and store/apply that.

However, I was under the impression this would happen automatically when using Fiori Elements.
Apparently it doesn’t. The captured app state does not include any changes to the underlying SmartTable in
a List Report. Is that correct John Patterson ?

[1] https://sapui5.hana.ondemand.com/#/api/sap.ui.comp.state.UIState

Like (0)

Find us on

Privacy Terms of Use

Legal Disclosure Copyright

Trademark Çerez Terc hler

Newsletter Support

You might also like