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 a overlay panel to show detail info. In the standard controller, the sub items is nested in its parent.

 

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

  • The controller.js take reponsible 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 image or panel in the side menu. we can add our own 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 aggregation by code.

Of course, you can define them in the XML view. Just 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 expand 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 own aggregation and overwrited some original method to fulfill our specific requriement.

5. Render

The method “render” is mandatory in custom controller. It is used to create html element for 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/ ‎

Sara Sampaio

Sara Sampaio

Author Since: March 10, 2022

0 0 votes
Article Rating
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x