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=Ch...
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