Show TOC

Step 12: Aggregation Binding Using TemplatesLocate this document in the navigation structure

Aggregation binding allows a control to be bound to a list within the model data and allows relative binding to the list entries by its child controls.

It will automatically create as many child controls as are needed to display the data in the model using one of the following two approaches:
  • Use template control that is cloned as many times as needed to display the data.

  • Use a factory function to generate the correct control per bound list entry based on the data received at runtime.

Preview
Figure 1: List with aggregation binding
Coding

You can view and download all files in the Explored app in the Demo Kit under Data Binding - Step 12.

webapp/index.html
...
	<script>
		// Attach an anonymous function to the SAPUI5 'init' event
		sap.ui.getCore().attachInit(function () {
			var oProductModel = new sap.ui.model.json.JSONModel();
			oProductModel.loadData("./model/Products.json");
			sap.ui.getCore().setModel(oProductModel, "products");
			var oModel = new sap.ui.model.json.JSONModel({
				firstName: "Harry",
				lastName: "Hawk",
				enabled: true,
				address: {
					street: "Dietmar-Hopp-Allee 16",
					city: "Walldorf",
					zip: "69190",
					country: "Germany"
				},
				"salesToDate" : 12345.6789,
				"currencyCode" : "EUR"
			});
...
webapp/view/App.view.xml
...				<Input width="200px" enabled="{/enabled}" description="{/currencyCode}"
						value="{ parts: [{path: '/salesToDate'}, {path: '/currencyCode'}], type: 'sap.ui.model.type.Currency', formatOptions: {showMeasure: false } }"/>
			</l:VerticalLayout>
		</content>
	</Panel>
	<Panel headerText="{i18n>panel3HeaderText}" class="sapUiResponsiveMargin" width="auto">
		<content>
			<List headerText="{i18n>productListTitle}" items="{products>/Products}">
				<items>
					<ObjectListItem title="{products>ProductName}"
									number="{	parts:
													[
														{path: 'products>UnitPrice'},
														{path: '/currencyCode'}
													],
												type: 'sap.ui.model.type.Currency',
												formatOptions: { showMeasure: false }
											}"
									numberUnit="{/currencyCode}">
						<attributes>
							<ObjectAttribute text="{products>QuantityPerUnit}"/>
							<ObjectAttribute title="{i18n>stockValue}"
											 text="{	parts: [
											 					{path: 'products>UnitPrice'},
											 					{path: 'products>UnitsInStock'},
											 					{path: '/currencyCode'}
											 					],
														formatter: '.formatStockValue'
													}" />
						</attributes>
					</ObjectListItem>
				</items>
			</List>
		</content>
	</Panel>

</mvc:View>

We add a new panel to the view.

webapp/controller/App.controller.js
sap.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", {
		formatMapUrl: function(sStreet, sZip, sCity, sCountry) {
			return "https://maps.googleapis.com/maps/api/staticmap?zoom=13&size=500x300&markers="
			+ jQuery.sap.encodeURL(sStreet + ", " + sZip +  " " + sCity + ", " + sCountry);
		},
		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");
		}
	});
});
webapp/model/Products.json (New)
{ "Products": [ {
     "ProductID": 1,
     "ProductName": "Chai",
     "SupplierID": 1,
     "CategoryID": 1,
     "QuantityPerUnit": "10 boxes x 20 bags",
     "UnitPrice": "18.0000",
     "UnitsInStock": 39,
     "UnitsOnOrder": 0,
     "ReorderLevel": 10,
     "Discontinued": false
    }, {
     "ProductID": 2,
     "ProductName": "Chang",
     "SupplierID": 1,
     "CategoryID": 1,
     "QuantityPerUnit": "24 - 12 oz bottles",
     "UnitPrice": "19.0000",
     "UnitsInStock": 17,
     "UnitsOnOrder": 40,
     "ReorderLevel": 25,
     "Discontinued": true
    }, {
     "ProductID": 3,
     "ProductName": "Aniseed Syrup",
     "SupplierID": 1,
     "CategoryID": 2,
     "QuantityPerUnit": "12 - 550 ml bottles",
     "UnitPrice": "10.0000",
     "UnitsInStock": 0,
     "UnitsOnOrder": 70,
     "ReorderLevel": 25,
     "Discontinued": false
    }, {
     "ProductID": 4,
     "ProductName": "Chef Anton's Cajun Seasoning",
     "SupplierID": 2,
     "CategoryID": 2,
     "QuantityPerUnit": "48 - 6 oz jars",
     "UnitPrice": "22.0000",
     "UnitsInStock": 53,
     "UnitsOnOrder": 0,
     "ReorderLevel": 0,
     "Discontinued": false
    }, {
     "ProductID": 5,
     "ProductName": "Chef Anton's Gumbo Mix",
     "SupplierID": 2,
     "CategoryID": 2,
     "QuantityPerUnit": "36 boxes",
     "UnitPrice": "21.3500",
     "UnitsInStock": 0,
     "UnitsOnOrder": 0,
     "ReorderLevel": 0,
     "Discontinued": true
    }]
  }

We now use a new JSON model file for product data.

webapp/i18n/i18n.properties
... 
# Screen titles
panel1HeaderText=Data Binding Basics
panel2HeaderText=Adress Details
panel3HeaderText=Aggregation Binding

# Invoice List
invoiceListTitle=Invoices
statusA=New
statusB=In Progress
statusC=Done

# Product list
productListTitle=Product List
stockValue=Current Stock Value
webapp/i18n/i18n_de.properties
...
# Screen titles
panel1HeaderText=Data Binding Basics
panel2HeaderText=Adressdetails
panel3HeaderText=Aggregation Binding

# Invoice List
invoiceListTitle=Rechnungen
statusA=Neu
statusB=Laufend
statusC=Abgeschlossen

# Product list
productListTitle=Artikelliste
stockValue=Lagerbestand Wert

We add the missing texts.