13. Routing and Navigation
Routing and navigation are key mechanisms for building modern SAPUI5/Fiori applications, allowing you to manage transitions between screens, states, and URL parameters.
Key Concepts
- Router — the component responsible for matching URLs to displayed views.
- Route — a rule describing which view to show for a given URL.
- Target — the specific view or fragment to be displayed.
- Pattern — the URL pattern that determines which route to activate.
Why use routing?
- Enables SPA (Single Page Application) with clean URLs.
- Allows bookmarks and direct links to specific screens.
- Simplifies navigation history management (Back/Forward).
- Allows passing parameters between screens.
Routing configuration (Freestyle)
Routing is usually configured in the manifest.json file:
"routing": {
"config": {
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"viewPath": "my.app.view",
"controlId": "app",
"controlAggregation": "pages",
"bypassed": {
"target": "notFound"
},
"async": true
},
"routes": [
{
"pattern": "",
"name": "home",
"target": "home"
},
{
"pattern": "detail/{id}",
"name": "detail",
"target": "detail"
}
],
"targets": {
"home": {
"viewName": "Home",
"viewLevel": 1
},
"detail": {
"viewName": "Detail",
"viewLevel": 2
},
"notFound": {
"viewName": "NotFound"
}
}
}
Navigation between screens (Freestyle)
To navigate between screens, use the router:
this.getOwnerComponent().getRouter().navTo("detail", {
id: 42
});
"detail"— route name.{ id: 42 }— parameters that will appear in the URL and be available in the target controller.
Handling route parameters
In the target view's controller:
onInit: function() {
this.getOwnerComponent().getRouter()
.getRoute("detail")
.attachPatternMatched(this._onObjectMatched, this);
},
_onObjectMatched: function(oEvent) {
var sId = oEvent.getParameter("arguments").id;
// Use sId to load data
}
Back navigation
To return to the previous screen:
onNavBack: function() {
var oHistory = sap.ui.core.routing.History.getInstance();
var sPreviousHash = oHistory.getPreviousHash();
if (sPreviousHash !== undefined) {
window.history.go(-1);
} else {
this.getOwnerComponent().getRouter().navTo("home", {}, true);
}
}
Lazy Loading
For performance optimization, it is recommended to use async view loading ("async": true in the routing config).
Routing and navigation in Fiori Elements
In Fiori Elements, routing and navigation are implemented at the framework level and are closely tied to OData and annotations. The URL usually contains the binding context reflecting the entity's key fields.
Example URL for Object Page:
/webapp/index.html#/SalesOrderSet('500000001')
Example configuration in manifest.json (Fiori Elements):
"routing": {
"routes": [
{
"pattern": ":?query:",
"name": "list",
"target": "list"
},
{
"pattern": "SalesOrderSet({key})",
"name": "object",
"target": "object"
}
],
"targets": {
"list": {
"type": "Component",
"id": "list",
"name": "sap.suite.ui.generic.template.ListReport"
},
"object": {
"type": "Component",
"id": "object",
"name": "sap.suite.ui.generic.template.ObjectPage"
}
}
}
Navigation from ListReport to ObjectPage happens automatically when a row is selected, and the URL contains the key fields of the selected entity.
Example of custom navigation in an Extension controller:
onNavigateToObjectPage: function(oEvent) {
var oContext = oEvent.getSource().getBindingContext();
var sPath = oContext.getPath(); // e.g., "/SalesOrderSet('500000001')"
this.getOwnerComponent().getRouter().navTo("object", {
key: encodeURIComponent(sPath.match(/\('(.+)'\)/)[1])
});
}
Best Practice: Using OData binding context in routing (Freestyle and Fiori Elements)
A good practice is to use the OData binding context as routing arguments. This allows you to:
- Make URLs as transparent as possible, reflecting business entities (e.g., object keys).
- Ensure a direct link between displayed data and the URL.
- Simplify bookmarks and link sharing between users.
Implementation:
- When navigating, pass key fields (or binding path) as route parameters.
- When opening a page, bind the page to this context:
// Navigation
this.getOwnerComponent().getRouter().navTo("object", {
key: oContext.getProperty("ID")
});
// In the target controller's onInit
onInit: function() {
this.getOwnerComponent().getRouter()
.getRoute("object")
.attachPatternMatched(this._onObjectMatched, this);
},
_onObjectMatched: function(oEvent) {
var sKey = oEvent.getParameter("arguments").key;
var sPath = "/EntitySet('" + sKey + "')";
this.getView().bindElement({
path: sPath
});
}
Advantages:
- The browser URL shows the same keys as the UI.
- Easy to implement deep linking and state restoration.
- Increased transparency and predictability of navigation.
Tips and Best Practices
- Use meaningful route names and URL patterns.
- Don’t overload a single view with many routes — split into separate screens.
- For nested navigation (e.g., Master-Detail), use
viewLevelfor animations and correct navigation history. - Handle non-existent routes via
bypassedand a separate NotFound view. - For complex scenarios, use router events (
attachRouteMatched,attachBypassed, etc.). - In Fiori Elements, use standard templates and annotations for navigation between entities.