17 SAPUI5 Best Practices (+ Examples)

These are SAPUI5 best practices.

You’ll learn:

  • What you should do in SAPUI5
  • What you shouldn’t do in SAPUI5

If you want your application to stay nice and clean and to do other developers a favor, then this article is for you.

Let’s get started!

#1 Create Keys for CRUD Statements

If you do a CRUD operation with an OData Model in SAPUI5, generate a key and don’t set it manually. For example, a read operation.

The requirement is to read an element with the primary keys foo and bar.

Here’s an example without generating the key:

// in your controller

...

// get model
var oModel = this.getView().getModel();

// set path with primary keys in a String
var sPath = "/Products(ProductID1='foo',ProductID2='bar')";

// read the product with the primary keys foo and bar
oModel.read(sPath, {

  success: function(oData) { sap.base.Log.info(oData); },
  error: function(oData) { sap.base.Log.info(oData); }

});

...

It works, but has a few drawbacks compared with a key generation.

For example, here’s how you do it with generating the key:

// in your controller

...

// get model
var oModel = this.getView().getModel();

// create primary keys with key generation
var sPath = oModel.createKey("/Products", {

  ProductID1: "foo",
  ProductID2: "bar"

});

// read the product with the primary keys foo and bar
oModel.read(sPath, {

  success: function(oData) { sap.base.Log.info(oData); },
  error: function(oData) { sap.base.Log.info(oData); }

});

...

Using the key generation has these advantages:

  • The key gets formatted automatically: The key gets formatted into the right format for the primary key specified in the OData service. For example, if the key is 0 but in the OData service the key is defined as Boolean, then the 0 gets automatically formatted as false. Awesome!
  • If there’s more than one key, then the keys get aligned correctly: For example, there’s a PrimaryKey1 and a PrimaryKey2. If they get mixed up in the wrong order, the read request fails. But the key generation takes care of the order. If keys are in the wrong order, the key generation takes care of it. The keys become aligned in the right order, and the read request succeeds.

#2 Use sap.base.Log Instead of console.log();

Because some browsers don’t support the console object and the developer tools aren’t available, use sap.base.Log.info instead.

There are different log levels:

  • all
  • debug
  • error
  • fatal
  • info
  • none
  • trace
  • warning

For example:

// in your controller
...
 
onInit: function() {

  sap.base.Log.info("view is instantiated");

},

onExit: function() {

  sap.base.Log.all("view is destroyed");

}

...

#3 Use the Hungarian Notation for Variable and Object Property Names

Use the Hungarian notation:

In Hungarian, variable and object properties are prefixed with the type of the variable in small letters. Followed by a capital letter for the variable name.

This is the list of prefixes for the data types:

For example:

// string
var sPath = "/Products";

// array
var aFruits = ["Banana", "Mango", "Kiwi"];

// object and object properties
var oAddress = {
  
  sStreet: "A Street Way",
  iHouseNumber: 1,

  oName: {
  
    firstName: "foo",
    lastName: "bar"
  
  }

};

#4 Use Camel Case for Variable and Function Names

Camel case means if a name consists of more than one word, each word is capitalized and without spaces or other characters in between.

For example:

// one word variable name - no camel case needed
sFruit = "Banana";

// one word function name - no camel case
function say() { sap.base.Log.info("foo") };

// more than one word - camel case
sBananaMango = "Is so tasty!";

// same same
function sayNow() { sap.base.Log.info("bar") };

#5 Use an Underscore for Private Object Property Names

If an object property is supposed to be private, then its name is supposed to start with a _. For example, _sPrivateVariable or _fnPrivateFunction.

An object property is private when it is invoked only within the object where it is set.

For example, in a controller object of the class sap.ui.core.mvc.Controller or in a component object of the class sap.ui.core.Component:

// in your controller
 or component
...
    
// private variable in the controller object
_sPrivateVariable = "foo",

// private function in the controller object
_fnPrivateFunction: function() {

  sap.base.Log.info("bar");

}

...

#6 Use Hyphens and Lowercase Letters for ID Names

Concatenate an ID with hyphens and put it all in lowercase.

For example:

<!-- in your xml view -->
...

<Button id="sap-m-button-id"
  press="onButtonPress">
</Button>

...

And NOT like this:

<!-- in your xml view -->
...

<Button id="saPMButtonID"
  press="onButtonPress">
</Button>

...

#7 i18n Naming Conventions

An i18n key is supposed to be written in camel case. Each key-value pair is supposed to be commented.

Use ALT + C in Web IDE to generate an i18n key-value-pair with an auto-generated comment.

For example:

# in your i18n

#XTIT: Application name
appTitle=Foo

#YDES: Application description
appDescription=Bar

#8 Use a Base Controller

Use a base controller for bigger applications.

The base controller is the one that extends all the others.

The base controller has methods that are common across the controllers.

For example, the base controller could have a getModel method. In the method goes this.getView().getModel(). Now all controller can use the shortcut this.getModel() instead of this.getView().getModel().

For example:

// in your base controller.
...

getModel: function() {

  return this.getView().getModel();

}
// in your controller


sap.ui.define([
  "./BaseController"
], function(BaseController) {
  "use strict";
 
  return BaseController.extend("my.application.controller.BaseController", {
    
 
   ...

    onRouteMatched: function() {
       
      var oModel = this.getModel();
     
      ... 

    }
 
});

#9 Share Common Events of Controllers Between Controllers with the EventBus

Use the sap.ui.core.EventBus to share common methods between controllers.

For example:

// in your controller 1
...
 
onInit: function() {
 
  var oEventBus = sap.ui.getCore().getEventBus();
  oEventBus.subscribe("_onButtonPress", this._onButtonPress, this);
 
},
 
onButtonPress: function(oEvent) {
 
  var oData = {
    message: "View 1 button was clicked."
  };
 
  var oEventBus = sap.ui.getCore().getEventBus();
  oEventBus.publish("_onButtonPress", oEvent, oData);
 
}

...
// in your controller 2
...
 
onButtonPress: function(oEvent) {
 
  var oData = {
    message: "View 2 button was clicked."
  };
 
  var oEventBus = sap.ui.getCore().getEventBus();
  oEventBus.publish("_onButtonPress", oEvent, oData);
 
}
 
...

# 10 Use Falsy and Truthy in a Controller

In the JavaScript parts of SAPUI5 use falsy and truthy, for example in the controllers.

A falsy is a value that is false when it is accessed in a Boolean context.

For example:

// in your controller
...

var sFoo = ""; // false in a boolean context like a if statement

if (sFoo) { // false

    sap.base.Log.info("bar"); // does not print bar

} else {

    sap.base.Log.info("foo"); // prints foo
 instead

}

...

10 falsy values exist in JavaScript:

  1. false
  2. undefined
  3. null
  4. 0
  5. 0n
  6. NaN
  7. “”
  8. document.all

A truthy value is a value that is true when it is accessed in a Boolean context. Every value is a truthy except it is a falsy.

For example:

// in your controller
...

var sFoo = []; // true in a boolean context like a if statement

if (sFoo) { // true

    sap.base.Log.info("bar"); // prints bar

} else {

    sap.base.Log.info("foo"); // does not print foo

}

...

This are examples of truthy values:

  • true
  • {}
  • []
  • “0”
  • “foo”
  • new Date()
  • 3.14
  • -3.14

#11 Use Consistence XML Formatting

If an element has more than two attributes then do a line break before the first attribute.

For example:

// in your XML view
...

<n:ActionButton
    title="{i18n>details}"
    icon="person-placeholder"
    press="onDetailsPress"/>

...

If an XML element has only one attribute then do not a line break.

For example:

// in your XML view
...

<n:ActionButton icon="person-placeholder"/>

...

If an XML element does not contain any aggregations, then don’t use a closing tag but a forward slash / in order to close the XML element. And no space before the forward slash /.

However, a space before the forward slash is a matter of taste—but if you don’t do that, you save a space every time. Over time, that makes a difference.

For example:

// in your XML view
...

<n:actionButtons>

  <n:ActionButton
    title="{i18n>details}"
    icon="person-placeholder"
    press="onDetailsPress"/> 

  <n:ActionButton
    title="{i18n>link}"
    icon="chain-link"
    press="onLinkPress"/>

</n:actionButtons>

...

And not like this:

// in your XML view
...

<n:actionButtons>

  <n:ActionButton
    title="{i18n>details}"
    icon="person-placeholder"
    press="onDetailsPress"> 
  </n:ActionButton>

  <n:ActionButton
    title="{i18n>link}"
    icon="chain-link"
    press="onLinkPress">
  </n:ActionButton>

</n:actionButtons>

...

Give your XML code space to breathe—don’t just write lines after lines like this:

<!-- in your XML view -->

<mvc:View
  controllerName="my.app.controller.Foo"
  xmlns:mvc="sap.ui.core.mvc"
  xmlns="sap.m">
  <App>
    <pages>
      <Page title="{i18n>pageTitle}">
        <content>
          <Panel headerText="{i18n>panelTitle}">
            <content>
              <Button
                text="{i18n>buttonText}"
                press=".onButtonPress"/>
                <Input
                  width="60%"
                  valueLiveUpdate="true"
                  value="{/customer/name}"
                  description="Changed {/recipient/name}"/>
            </content>
          </Panel>
        </content>
      </Page>
    </pages>
  </App>
</mvc:View>

Do systematic breaks, instead: insert empty lines around your XML views according to a pattern.

One way to make an XML view easier to read for yourself and others is to have an empty code line before and after every:

  • Opening XML tag of a control
  • Closing XML tag of a control

But not before the first and last XML tag in the view.

For example:

<!-- in your XML view -->

<mvc:View
  controllerName="my.app.controller.Foo"
  xmlns:mvc="sap.ui.core.mvc"
  xmlns="sap.m">
  
  <Button
    text="{i18n>buttonText}"
    press=".onButtonPress"/>
                
  <Input
    width="60%"
    valueLiveUpdate="true"
    value="{/customer/name}"
    description="Changed {/recipient/name}"/>
            
</mvc:View>

Furthermore, to put only an empty line before and not after the opening XML tag for a control, if the control is an aggregation.

The other way around, to put an empty line after an XML tag of a control, rather than before, if the control is part of an aggregation.

For example:

<!-- in your XML view -->

<mvc:View
  controllerName="my.app.controller.Foo"
  xmlns:mvc="sap.ui.core.mvc"
  xmlns="sap.m">
  
  <App>
    <pages>
      
      <Page title="{i18n>homePageTitle}">
        <content>
          
          <Panel headerText="{i18n>panelTitle}">
            <content>
              
              <Button
                text="{i18n>buttonText}"
                press=".onButtonPress"/>
                
                <Input
                  width="60%"
                  valueLiveUpdate="true"
                  value="{/customer/name}"
                  description="Changed {/recipient/name}"/>
            
            </content>
          </Panel>
        
        </content>
      </Page>
    
    </pages>
  </App>

</mvc:View>

Do you see how much more enjoyable it is to read the last code sample with empty lines compared to the first code sample without empty lines?

Just do it—if not for you, then for everyone who might read your code at some point.

#14 Use Only the ID of an SAP Icon

If you use XML views then do not pass sap-icon://the-icon to the control’s icon property but instead the-icon.

Just omit the sap-icon://. Because you can.

For example:

// in your XML view
...

<Button icon="accept"/>

...

And not like this:

// in your XML view
...

<Button icon="sap-icon://accept"/>

...

#15 Do Not Concatenate More Than Three Expressions in a Controller

In a controller, formatter, component, and so on (anything with JavaScript), don’t concatenate more than three expressions. More than three concatenated expressions could be hard to read and understand for others.

As a rule of thumb: Not more than three dots. Exception: this keyword.

For example:

// in your controller

// do NOT do this
var sText = this.getView().getModel("i18n").getResourceBundle().getText("foo");

// do this for easy read- and comprehensibility
var oResourceBundle = this.getView().getModel("i18n").getResourceBundle();
var stext = oResourceBundle.getText("foo");

// or even like that; matter of taste
var oIntModel = this.getView().getModel("i18n");
var oResourceBundle = oIntModel.getResourceBundle();
var sText = oResourceBundle.getText("foo");

#16 Avoid Using Naked Functions as Arguments

Do not pass naked functions as arguments to a function in a controller, a formatter, a component, and so on (anything with JavaScript).

Use in the controller as object property assigned functions instead—except the function is trivial.

For example, a naked function as an argument (don’t do it like this):

// in your controller
...  

var oRouter = this.getRouter();

// do not pass a naked function as an argument
 as here
oRouter.attachRouteMatched(function(oEvent) {
	  
var sRouteName = oEvent.getParameter("name");
	    
  if (sRouteName === "employee") {
              
    this._onRouteMatched(oEvent);

   }

 }, this);
		
}
  
...

Use a controller object property assigned function instead:

// in your controller
...

onInit: function() {

  var oRouter = this.getRouter();

  // do pass a function assigned as object property to the controller
  oRouter.getRoute("foo").attachRouteMatched(this._onRouteMatched, this);

},

_onRouteMatched: function() {

  // do anything

}

...

#17 Do not Use SAPUI5 Methods & Object Properties That Start with a _

If you check an SAPUI5 object in a debugger then you will usually find object properties that start with one or two _. For example, _getFoo() or __bar.

Do not use those methods and objects properties, even if they seem useful in some cases. They are private for a reason and might change with the next version—if so, and you use any of those object properties, then you need to fix it.

Leave a Comment