15 Best Practices for SAP UI5

UI5
Hand playing piano.

Best practices collection for SAP UI5. Please leave a comment if you would like to contribute a best practice or to make any other remark.

Create Keys for CRUD Statements

If you do a CRUD operation with an OData Model in SAP UI5 then generate a key for the operation. For example, for a read operation. The aim is to read an element which has the primary keys foo and bar:

// controller
// without key generation

// 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); }

});

This works. But has several disadvantages in compare to a key generation:

// controller
// with key generation

// 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); }

});

To use the key generation has those advantages:

  • The key gets formatted automatically. The key gets formatted into the right format of the primary key specified in the OData service. For example, if the key is stated as 0 but in the OData service, the key is defined as a Boolean, then the 0 gets automatically formatted to false.
  • If there is more than one key, then the keys get aligned in the correct order. For example, there is a PrimaryKey1 and a PrimaryKey2. If those get mixed up in the wrong order in a path as a String as in the first code sample, then the read request fails. But the key generation takes care of the right order. If the order of the keys is mixed up in the key generation as in the second code sample, then the key generation sorts it out. The key gets aligned in the right order, and the read request succeeds.

Do Not Use console.log();

Because the console object is not available within certain browsers while the developer tools are not available, instead, use sap.base.Log.info. There are different log levels:

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

For example:

// in your controller

sap.ui.define([
  "sap/ui/core/mvc/Controller"
], function(Controller) {
  "use strict";
 
  return Controller.extend("my.app.controller.Controller", function() {
 
    onInit: function() {

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

    },

    onExit: function() {

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

    }

  });

});

Variable & Object Property Names

Use the Hungarian notation. In the Hungarian Notation variable and object property names are prefixed with an indicator for the type of the variable in small letters. Then continue with a capital letter for the variable name. This is the list for the 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"
  
  }

};

Use Camel Case for Variable and Function Names

Camel case means that 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") };

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 only invoked within the object where it is set. For example, a controller object of the class sap.ui.core.mvc.Controller or a component object of the class sap.ui.core.Component.

// in your controller

sap.ui.define([
  "sap/ui/core/mvc/Controller"
], function(Controller) {
  "use strict";
 
  return Controller.extend("my.app.controller.Controller", function() {
  
    // private variable in the controller object
    _sPrivateVariable = "foo",

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

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

    }

  });  

});

Use Hyphens and Lowercase Letters for ID Names

Concatenate an ID by Hyphens and put it all in lowercase letters:

<!-- right id with hyphens and lowercase letters -->
<Button id="sap-m-button-id"
  press="onButtonPress">
</Button>

<!-- wrong id -->
<Button id="saPMButtonID"
  press="onButtonPress">
</Button>

i18n Naming Conventions

An i18n key is supposed to be written in camel case. And each key-value-pair is supposed to be commented. Use in the Web IDE the shortcut ALT + C to generate an i18n key-value-pair with an auto-generated comment.

#XTIT: Application name
appTitle=Foo

#YDES: Application description
appDescription=Bar

Use a Base Controller

Create for bigger applications a base controller. The base controller extends all other controllers. In the base controller go methods which are common in the controllers.

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

See here for what a base controller exactly is an how to use it.

Share Common Events of Controllers Between Controller with the EventBus

Use the sap.ui.core.EventBus to share common methods between controllers. Here is explained what the event bus is and how to use it.

Use Falsy and Truthy in a Controller

In the JavaScript parts of SAP UI5 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:

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

}

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:

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

Use Consistence XML Formatting

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

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

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

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

If an XML element does not contain any aggregations, then do not 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 do no forward slash you save every time a space, obviously. That can make a difference over the long run.

Do this:

<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 do not this:

<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>

In your XML files give the code space to breathe – do not just write your XML code line after line 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>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>

Rather do systematical breaks; insert empty code of lines in your XML views according to a pattern.

One great pattern that makes an XML view much more easy to read for yourself and others is to put an empty code of 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 of an XML 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 code of line before and not after an opening XML tag of a control if after the control an aggregation of the control follows.

And the other way around, to put only an empty code of line after and not before a closing XML tag of a control if after the control an aggregation of the control follows.

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 of a pleasure it is to read the last code sample with the empty code of lines in comparison to the first code sample without empty code of lines at all?

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://.

Do this:

<Button icon="accept"/>

And do not this:

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

Do Not Concatenate More Than Three Expressions in a Controller

In a controller and therefore, in JavaScript, do not concatenate more than three expressions. More than three concatenated expressions could be hard to read and comprehend easily for others.

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

// 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");

Avoid Using Naked Functions as Arguments in a Controller

Do not pass naked functions as arguments to a function in a controller. Use in the controller as object property assigned functions instead – except the function is trivial.

For example, do not use a naked function as an argument …

// in your controller
  
sap.ui.define([
  "sap/ui/core/mvc/Controller"
], function(Controller) {
  "use strict";
   
  return Controller.extend(function() {
 
    onInit: function () {
    
      var oRouter = this.getRouter();

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

        }

      }, this);
		
    }
  
  });

});

… but rather use a controller object property assigned function …

// in your controller
  
sap.ui.define([
  "sap/ui/core/mvc/Controller"
], function(Controller) {
  "use strict";
   
  return Controller.extend(function() {
 
    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 not Use SAP UI5 Methods & Object Properties That Start with a _

If you check an SAP UI5 object in a debugger then you will usually come across object properties that start with one or two _, for example, _getFoo() or __bar. Do not use those methods and object properties even if it is tempting in some cases.

There is a reason why this method or object property was marked with a prefixed underscore and therefore as private or protected.

Methods and object properties that are marked with an underscore are not safe for upgrades – they may change their names or event the code inside the methods changes.

If you use private or protected methods or object properties marked with an _ or __ then your application may break with the next SAP UI5 update.

1 Comment

Most Recent Articles

Will SAP UI5 replace the SAP Web UI?

SAP Full Forms

More Similar Articles

1 Comment. Leave new

Request you to please provide an article on “UI5 advanced programming model” including separation of concerns concept.

Your articles are really easy to understand! Thanks for doing the great work for UI5 community.

Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.

Menu