Technical Articles
Custom Controller in SAPUI5: Step 1
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: {
/*...*/
- The sideNavigtion is base controller, we will create our own custom controller by extending SideNaviagtion.
- 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/