Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
frank_xie
Product and Topic Expert
Product and Topic Expert
0 Kudos
1,700
In the blog, I'd like to share with you how to modify the standard side navigation behavior by using custom controller.

When I expand standard side navigation, it looks like:

https://ui5.sap.com/#/entity/sap.tnt.SideNavigation/sample/sap.tnt.sample.SideNavigation


In our custom controller, it will looks like this:


You can see, it's a big change. In the expanded state, there will be an overlay panel to show detailed info. In the standard controller, the sub-items are nested in its parent.

 

Before starting, if you want to extend a controller, normally you need to modify the controller.js file and controllerRender.js file.

  • The controller.js take responsible for properties, aggregations, event handlers, and so on.

  • The controllerRender.js take charge of building html element and CSS class. It renders the controller.


If you are the first time to touch the topic, I recommend you to read the tutorial firstly https://ui5.sap.com/#/topic/d12d2ee6a5454d799358d425f9e7c4db

In this blog, we focus on the controller.js.

1. Define custom controller
sap.ui.define([
"sap/tnt/SideNavigation",
"SimpleDemo/container/SideMenuRender",
"SimpleDemo/container/SideMenuList",
"sap/m/Image",
"sap/ui/core/Fragment"
], function (SideNavigation, SideMenuRender, SideMenuList, Image, Fragment) {
"use strict";
return SideNavigation.extend("SimpleDemo.container.SideMenu", {
metadata: {
aggregations: {
/*...*/


  1. The sideNavigtion is base controller, we will create our own custom controller by extending SideNaviagtion.

  2. The parameter in extend("") is the path for your custom controller.


In the project, the structure looks like:


So, now I name my custome controller "SideMenu".

 

2. What's aggregation?

Since I plan to add more elements like images or panels in the side menu. we can add our aggregation in our custom controller.

In the aggregation, you can define which controller can be nested in the custom controller.
/*...*/
metadata: {
aggregations: {
image: {
type: "sap.m.Image",
multiple: false
},
panel: { type: "sap.ui.core.Control", multiple: false },
items: { type: SideMenuList, multiple: true, singularName: "item" },
},
events: {
}
},
init: function () {
this.setAggregation("image", new Image({
src: "{/ProfileImage}",
// width: "84%"
width: "45px"
}).addStyleClass("sapUiSmallMarginBottom sideMenuImage"));
var ofooter = new sap.tnt.NavigationList();
ofooter.addItem(new sap.tnt.NavigationListItem({
icon: "sap-icon://menu2"
}));
this.setAggregation("footer", ofooter);

var that = this;
Fragment.load({
name: "SimpleDemo.fragments.ItemPanel",
controller: this
}).then(function (oPanel) {
that.setAggregation("panel", oPanel);
});
/*...*/

Then, in the function "init". I set these aggregations by code.

Of course, you can define them in the XML view. Just a different view to implement the aggregation.

3. Modify the prototype method

In our case, we need to extend the original method like "_itemSelectionHandler" in SideNavigation. Because when one item is selected, there will be a new panel not expanding itself. The way is to overwrite its prototype directly in the init method.
/*...*/
Fragment.load({
name: "SimpleDemo.fragments.ItemPanel",
controller: this
}).then(function (oPanel) {
that.setAggregation("panel", oPanel);
});

SideNavigation.prototype.init.call(this);

SideNavigation.prototype._itemSelectionHandler = function (event) {
var item = event.getParameter('item');
if (item.getKey() !== "workArea") {
this.setSelectedItem(item);
this.fireItemSelect({
item: item
});
SideMenuRender.hasItemPanel = false;
this.rerender();
} else {
//Register event click outside side menu
this.delegate = {
onclick: this.closeItemPanel.bind(this)
};
//this.getParent().byId("pageContainer").addEventDelegate(this.delegate)
if (SideMenuRender.hasItemPanel) {
//When user just click the second item but not navigation
this.closeItemPanel();
} else {
SideMenuRender.hasItemPanel = true;
this.rerender();
}
}
};

SideNavigation.prototype.onAfterRendering = function () {

};

SideNavigation.prototype.onBeforeRendering = function () {

};
/*...*/

OK, until now. The modification in controller.js is complete. We added our aggregation and overwrote some original methods to fulfill our specific requirement.

5. Render

The method "render" is mandatory in custom controller. It is used to create html elements for the controller and assign CCS properties.

In this case, we need the render class to render the panel and control its position and layout.


Refer:

Simple tutorial in Demo Kit

https://ui5.sap.com/#/topic/d12d2ee6a5454d799358d425f9e7c4db https://ui5.sap.com/#/topic/21515f09c0324218bb705b27407f5d61

OpenUI5 Source code

openui5/src at master · SAP/openui5 · GitHub

Next blog

https://blogs.sap.com/2023/06/01/custom-controller-in-sapui5-step-2/ ‎