
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 under Data Binding - Step 15.
...
<attributes>
<ObjectAttribute text="{ path: 'Status', formatter: '.getStatusText' }"/>
</attributes>
</ObjectListItem>
</items>
</List>
</content>
</Panel>
<Panel headerText="{i18n>panel4HeaderText}" class="sapUiResponsiveMargin" width="auto">
<content>
<List id="ProductList" headerText="{i18n>productListTitle}" />
</content>
</Panel>
</mvc:View>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.
...
productListFactory: function(sId, oContext) {
var oUIControl = null;
// Define the item description
var sDescription = oContext.getProperty("ProductName") +
" (" + oContext.getProperty("QuantityPerUnit") + ")";
// Is this item is both out of stock *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: [{path: "products>UnitPrice"},
{path: "/currencyCode"}],
type: "sap.ui.model.type.Currency",
formatOptions: {showMeasure: false}
},
numberUnit : { path: "/currencyCode"}
});
// Is this item in stock?
if (oContext.getProperty("UnitsInStock") > 0) {
// First object attribute displays the current stock level
oUIControl.addAttribute(new sap.m.ObjectAttribute({
title : { path: "i18n>UnitsInStock" },
text : { path: "products>UnitsInStock" }
}));
// Second object attribute displays the current stock value
oUIControl.addAttribute(new sap.m.ObjectAttribute({
title : { path: "i18n>stockValue" },
text : { parts: [{path: "products>UnitPrice"},
{path: "products>UnitsInStock"},
{path: "/currencyCode"}],
formatter: this.formatStockValue }
}));
// Has this product been discontinued?
if (oContext.getProperty("Discontinued")) {
// Yup, so we're selling off the last remaining stock items
// Set the status of the first attribute to "discontinued"
oUIControl.setFirstStatus(new sap.m.ObjectStatus({
text: { path: "i18n>Discontinued" },
state: "Error"
}));
}
}
else {
// 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;
},
onInit: function() {
// Get a reference to the Product List using the XML element's id
var oProductList = this.getView().byId("ProductList");
// In addition to binding the "items" aggregation in the list to the Products array
// in the "products" model, the productListFactory function is also passed as a parameter
oProductList.bindAggregation("items", "products>/Products", this.productListFactory.bind(this));
}
...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, so add two ObjectAttributes to the ObjectListItem to display the current stock level and value. This is the majority case.
The product is in stock but has also been discontinued, so we are simply selling off the last remaining stock items. Therefore, in addition to the two ObjectAttributes added above, use the status property of the first attribute to indicate that this product has been discontinued.
The product has not been discontinued but 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.
...
# Product Details
...
outOfStock=Out of Stock...
# Product Details
...
outOfStock=Nicht VorrätigWe add the missing texts to the properties files.