After you have read the expression binding and custom formatter chapters of the SAPUI5 Walkthrough tutorial plus the SAPUI5 tutorial about data binding (in XML views) and implemented some easy use cases you may want to have a look at a more full-fledged examples to get an idea on what is possible – like displaying a relative date, adapting OData queries, or how to handle translations with placeholders. Luckily such sample applications exist, and in this blog post, I will show you some useful code snippets which can help you in your daily developer life.

Sample Application
You can find the sample applications in the SAP Web IDE in the Menu via File→ New → Project from Sample Application.

Select the Approve Purchase Orders application and click Next at the bottom of the screen. Agree to the license agreement on the next screen and click Finish.

You should now have a folder called nw.epm.refapps.ext.po.apv in your workspace.
In order to run the application, select the folder nw.epm.refapps.ext.po.apv, and click the green Play (Run) button.

In the pop-up that follows, choose flpSandboxMockServer.html to run the application with mock data.

Relative Date Formatting
Instead of displaying a date in a format like “Dec 9, 2016” wouldn’t it be a more human approach to display in a format like tomorrow, today or 2 hours ago? We know this way of displaying dates from Twitter or Instagram, but it is also possible within an SAPUI5 application, out of the box.

The included mock data from our sample application is from 2015, so we need to change it manually. We’ll go ahead and change the mock data for Purchase Orders. You can use the OData mock data editor to change the date values to a certain date, or you can use some JavaScript coding to create date and time values and manually change it in PurchaseOrders.json:

// Date(year, month, day, hour, minute)
// note that the month starts at 0!
date = new Date(2016, 11, 9, 13, 15);
// Fri Dec 09 2016 13:15:00 GMT+0100 (CET)
date.getTime()
// 1481285700000

I have changed some dates so that they are relative to today – like yesterday or two days ago – in my mock data. If you run the application again, you can already see the relative formatting applied:

Let’s now have a look at the code-snippet that made this formatting possible. You’ll find it in the S2_PurchaseOrders.view.xml.

<ObjectStatus id="changedAtObjectStatus" 
    text="{path: 'ChangedAt', type: 'sap.ui.model.type.Date',
        formatOptions: { style: 'medium',
                        strictParsing: true,
                        relative: true }}"/>

Two things are necessary for relative formatting to work. First, you need to define the type sap.ui.model.type.Date and the format option must be relative. You can also define the type sap.ui.model.type.DateTime to get a more granular formatting for displaying information like 2 hours ago:

Look at the Explored example for date and date time types for more formatting options:

sap.ui.model.type.Date
sap.ui.model.type.DateTime

Formatter Function
The formatter function enables you to manipulate the displayed info for a certain field, depending on the values for this field. Examples would be setting a different status (color) for the number of available items, displaying different text-templates, or displaying some things differently whether you are on a mobile phone or desktop device.

You could use formatter functions or expression binding for that kind of functionality. The former uses JavaScript coding and is suitable for bigger chunks of logic, the latter is written directly in XML. Let’s have a look at some formatter functions first.

In the S2_PurchaseOrders.view.xml you find a formatter function to display different texts depending on the number of items:

<ObjectAttribute id="itemCountObjectAttribute" 
    text="{path: 'ItemCount', formatter: '.formatter.items'}"/>

Coding in BaseController.js for the .formatter reference:

... return Controller.extend(
"nw.epm.refapps.purchaseorders.approve.controller.BaseController", {
formatter: formatter, ...

Coding in formatter.js:

items: function(iItems) {
    if (isNaN(iItems)) {
        return "";
    }
    var oBundle = this.getResourceBundle();
    return (iItems === 1) ? oBundle.getText("xfld.item") : oBundle.getText("xfld.items", [iItems]);
}

You’ll see depending on the number of items (=== 1 or not) different text templates are chosen: xfld.item or xfld.items. The [iItems] array is used to replace the {0} placeholder in the translation file i18n.properties file:

#XFLD: Number of items
xfld.items={0} Items
#XFLD: Exactly one item
xfld.item=1 Item

INFO: Placeholders are very useful if you deal with languages with different sentence structures. For example, you can put the {0} in another part of the text. You are not limited to one placeholder; you can use multiple placeholders like {1}, {2} or {3}.

I have adopted the mock data (ItemCount property for the purchase orders) to show the different cases:

See Custom Formatters in the Walkthrough Tutorial for more information.

Expression Binding
If you have little logic on how to format your data depending on different circumstances, you could also use expression binding, and write your coding directly into the XML view. In the S2_PurchaseOrders.view.xml, you’ll find several examples for that. I’ll show you a snippet where you can display a certain text and a replace a certain placeholder:

<ObjectListItem id="listItem" 
    intro="{parts:[{path: 'i18n>xfld.orderedBy'}, 
        {path: 'OrderedByName'}], 
        formatter: 'jQuery.sap.formatMessage'}" .../>

The first path inside parts is used to retrieve the right text, the second part will replace the {0} placeholder in the text. This is done automatically via the jQuery.sap.formatMessage formatter (18n> is the named model for translations). You find the text xfld.orderedBy inside the i18n.properties file:

#XFLD: Prefix to ordered-by attribute
xfld.orderedBy=Ordered by {0}

See Expression Binding in the Walkthrough Tutorial for more information.
Here’s the documentation about expression binding, too.

OData queries
When dealing with OData, you can provide some initial sorting or select via an URL parameter. An example for a sorting ($orderby) would look like this in the ES4 Demo Gateway system:
https://sapes4.sapdevcenter.com/sap/opu/odata/sap/EPM_REF_APPS_PO_APV_SRV/PurchaseOrders?$orderby=ChangedAt

In the S2_PurchaseOrders.view.xml, you’ll find an example on how to provide those parameters inside an XML view for an aggregation binding:

 

<List id="list" modeAnimationOn="false"
    ...
    items="{path: '/PurchaseOrders', 
         sorter: [{path: 'ChangedAt', descending: true}, 
        {path: 'POId', descending: false}], 
        parameters: {select:
          'POId,OrderedByName,SupplierName,
          GrossAmount,CurrencyCode,
          ChangedAt,ItemCount'}}"
.../>

Using the sorter, we can sort our data set. Using the select parameter, we can select only certain fields to keep the transferred data low. I have changed the descending of the ChangedAt sorting to false to see the latest purchase order at the top:

Read more about the aggregation binding within the Sorting, Grouping and Filtering section.

Conclusion
The SAPUI5 example applications are a great way to see a lot of different concepts in action in a full-fledged application. I hope you learned the one or the other new trick for your XML binding. Feel free to explore the app further and share your findings in the comments section.

Resources
SAPUI5 Data Binding Developer Guide
SAPUI5 Demo Kit → Developer Guide → Essentials → Data Binding

SAPUI5 Walkthrough Tutorial
Including examples for expression binding and formatters
SAPUI5 Demo Kit → Developer Guide → Tutorials → Walkthrough

SAPUI5 Data Binding Tutorial
SAPUI5 Demo Kit → Developer Guide → Tutorials → Data Binding

To report this post you need to login first.

1 Comment

You must be Logged on to comment or reply to a post.

Leave a Reply