Instead of hard-coding a single template control, we will use a factory function to generate different controls based on the data received at runtime. This approach is much more flexible and allows complex or heterogeneous data to be displayed.
You can view and download all files in the Explored app in the Demo Kit at Data Binding - Step 15.
#!xml...
<Panel headerText="{i18n>panel3HeaderText}" class="sapUiResponsiveMargin" width="auto">
<content>
<List id="ProductList" headerText="{i18n>productListTitle}" items="{
path: 'products>/Products',
factory: '.productListFactory'
}" />
</content>
</Panel>
...
The List XML element that previously held the product list is now reduced simply to a named, but otherwise empty placeholder. Without a factory function to populate it, this List would always remain empty.
#!jssap.ui.define([ "sap/ui/core/mvc/Controller", "sap/ui/model/type/Currency" ],
function(Controller, Currency) {
"use strict";
return Controller.extend("sap.ui.demo.db.controller.App", {
formatMail: function(sFirstName, sLastName) {
var oBundle = this.getView().getModel("i18n").getResourceBundle();
return sap.m.URLHelper.normalizeEmail(
sFirstName + "." + sLastName + "@example.com",
oBundle.getText("mailSubject", [sFirstName]),
oBundle.getText("mailBody"));
},
formatStockValue : function(fUnitPrice,
iStockLevel, sCurrCode) {
var sBrowserLocale = sap.ui.getCore().getConfiguration().getLanguage();
var oLocale = new sap.ui.core.Locale(sBrowserLocale);
var oLocaleData = new sap.ui.core.LocaleData(oLocale);
var oCurrency = new Currency(oLocaleData.mData.currencyFormat);
return oCurrency.formatValue([fUnitPrice * iStockLevel, sCurrCode ], "string");
},
onItemSelected : function(oEvent) {
var oSelectedItem = oEvent.getSource();
var oContext = oSelectedItem.getBindingContext("products");
var sPath = oContext.getPath();
var oProductDetailPanel = this.getView().byId("productDetailsPanel");
oProductDetailPanel.bindElement({path : sPath, model : "products"});
},
productListFactory : function(sId,oContext) {
var oUIControl = null;
// Define the item description
var sDescription = oContext.getProperty("ProductName") + " (" + oContext.getProperty("QuantityPerUnit") + ")";
// This item is out of stock and discontinued
// *and* discontinued?
if (oContext.getProperty("UnitsInStock") === 0 && oContext.getProperty("Discontinued")) {
// Yup, so use a
// StandardListItem
oUIControl = new sap.m.StandardListItem(sId, {
icon : "sap-icon://warning",
title : sDescription,
info : { path: "i18n>Discontinued" },
infoState : "Error"
});
} else {
// Nope, so we will create an
// ObjectListItem
oUIControl = new sap.m.ObjectListItem(sId, {
title : sDescription,
number : {
parts : [ "products>UnitPrice", "/currencyCode" ],
type : "sap.ui.model.type.Currency",
formatOptions : {
showMeasure : false
}
},
numberUnit : {
path : "/currencyCode"
}
});
// Is this item out of stock?
if (oContext.getProperty("UnitsInStock") < 1) {
// Nope, so this item is just temporarily out of stock
oUIControl.addAttribute(new sap.m.ObjectAttribute({
text : { path: "i18n>outOfStock" }
}));
}
}
// Set item active (so it is clickable) and attach the press event
// handler for showing the details
oUIControl.setType(sap.m.ListType.Active);
oUIControl.attachPress(this.onItemSelected, this);
return oUIControl;
}
});
});
In the App controller, we create a new function called productListFactory. The types of controls returned from this factory function must be limited to those suitable for inclusion in the items aggregation of a sap.m.List object. In this case, we will return either a StandardListItem or an ObjectListItem using the following logic:
First, eliminate the minority case.
If the stock level is zero and the product has also been discontinued, then use a StandardListItem with a warning icon and a Product Discontinued message in the status property. All other possibilities will use an ObjectListItem.
Create an ObjectListItem then for the remaining three possibilities.
The product is in stock and the product has not been discontinued. This is the majority case.
The stock level is zero, therefore we are temporarily out of stock. In this case, add a single ObjectAttribute that displays the Out of Stock message.
#!properties...
# Product Details
...
outOfStock=Out of Stock
#!properties...
# Product Details
...
outOfStock=Nicht Vorrätig
We add the missing texts to the properties files.
That's all - you completed the Data Binding tutorial!