19 KiB
SAPUI5 Data Binding & Models
Source: Official SAP SAPUI5 Documentation Documentation: https://github.com/SAP-docs/sapui5/tree/main/docs/04_Essentials Last Updated: 2025-11-21
Data Binding Overview
Data binding connects UI controls to data sources, automatically synchronizing changes bidirectionally.
Key Benefits:
- Automatic UI updates when data changes
- Reduced boilerplate code
- Clean separation of data and presentation
- Type conversion and formatting
- Validation support
Binding Types:
- Property Binding: Single value (text, enabled, visible)
- Aggregation Binding: Collections (table items, list items)
- Element Binding: Object context
- Expression Binding: Inline calculations
Documentation: https://github.com/SAP-docs/sapui5/tree/main/docs/04_Essentials (search: binding, data-binding)
Binding Modes
One-Way Binding:
- Data flows model → view only
- UI updates when model changes
- User input doesn't update model
- Use for read-only data
// In manifest.json
"models": {
"": {
"dataSource": "mainService",
"settings": {
"defaultBindingMode": "OneWay"
}
}
}
Two-Way Binding:
- Data flows model ↔ view bidirectionally
- Model updates when user changes input
- View updates when model changes
- Use for editable forms
"defaultBindingMode": "TwoWay"
One-Time Binding:
- Data loaded once at initialization
- No updates after initial load
- Best performance for static data
<Text text="{path: '/title', mode: 'OneTime'}"/>
Documentation: https://github.com/SAP-docs/sapui5/tree/main/docs/04_Essentials (search: binding-mode)
Model Types
JSON Model
Client-side model for JavaScript objects. Best for small datasets and local data.
Creation:
// In controller
var oModel = new JSONModel({
products: [
{ id: 1, name: "Product 1", price: 100 },
{ id: 2, name: "Product 2", price: 200 }
],
selectedProduct: null
});
this.getView().setModel(oModel);
From File:
var oModel = new JSONModel();
oModel.loadData("model/data.json");
this.getView().setModel(oModel);
Usage:
<List items="{/products}">
<StandardListItem
title="{name}"
description="Price: {price}"/>
</List>
Key Methods:
setData(oData): Set complete datasetProperty(sPath, oValue): Set single propertygetProperty(sPath): Get property valueloadData(sURL): Load from URL
Documentation: https://github.com/SAP-docs/sapui5/tree/main/docs/04_Essentials (search: json-model)
OData V2 Model
Server-side model for OData v2 services. Automatic CRUD operations.
Creation:
// In manifest.json
{
"sap.app": {
"dataSources": {
"mainService": {
"uri": "/sap/opu/odata/sap/SERVICE_SRV/",
"type": "OData",
"settings": {
"odataVersion": "2.0",
"localUri": "localService/metadata.xml"
}
}
}
},
"sap.ui5": {
"models": {
"": {
"dataSource": "mainService",
"settings": {
"defaultBindingMode": "TwoWay",
"defaultCountMode": "Inline",
"useBatch": true
}
}
}
}
}
Reading Data:
// Simple read
this.getView().getModel().read("/Products", {
success: function(oData) {
console.log(oData);
},
error: function(oError) {
MessageBox.error("Failed to load data");
}
});
// With filters and sorters
this.getView().getModel().read("/Products", {
filters: [new Filter("Price", FilterOperator.GT, 100)],
sorters: [new Sorter("Name", false)],
urlParameters: {
"$expand": "Category"
},
success: function(oData) {
console.log(oData);
}
});
Creating Entries:
var oModel = this.getView().getModel();
oModel.create("/Products", {
Name: "New Product",
Price: 150,
CategoryID: 1
}, {
success: function() {
MessageToast.show("Product created");
},
error: function(oError) {
MessageBox.error("Failed to create product");
}
});
Updating Entries:
var oModel = this.getView().getModel();
oModel.update("/Products(1)", {
Price: 200
}, {
success: function() {
MessageToast.show("Product updated");
}
});
Deleting Entries:
oModel.remove("/Products(1)", {
success: function() {
MessageToast.show("Product deleted");
}
});
Batch Requests:
oModel.setUseBatch(true);
oModel.setDeferredGroups(["myGroup"]);
// Add to batch
oModel.create("/Products", oData, { groupId: "myGroup" });
oModel.create("/Products", oData2, { groupId: "myGroup" });
// Submit batch
oModel.submitChanges({
groupId: "myGroup",
success: function() {
MessageToast.show("Batch successful");
}
});
Key Settings:
useBatch: Enable batch requestsdefaultCountMode: How to get counts (Inline, Request, None)refreshAfterChange: Auto-refresh after updatesdefaultBindingMode: One-way or two-way
Documentation: https://github.com/SAP-docs/sapui5/tree/main/docs/04_Essentials (search: odata-v2-model)
OData V4 Model
Modern OData v4 model with improved performance and features.
Creation:
// In manifest.json
{
"sap.app": {
"dataSources": {
"mainService": {
"uri": "/sap/opu/odata4/sap/service/srvd/sap/api/0001/",
"type": "OData",
"settings": {
"odataVersion": "4.0"
}
}
}
},
"sap.ui5": {
"models": {
"": {
"dataSource": "mainService",
"settings": {
"synchronizationMode": "None",
"operationMode": "Server",
"autoExpandSelect": true,
"earlyRequests": true
}
}
}
}
}
Key Differences from V2:
- Server-side operations (filter, sort, page)
- Automatic $expand and $select
- Better performance
- Stricter adherence to OData standard
- No client-side models
Reading with List Binding:
<Table items="{
path: '/Products',
parameters: {
$expand: 'Category',
$select: 'ID,Name,Price',
$filter: 'Price gt 100',
$orderby: 'Name'
}
}">
Creating Entries:
var oListBinding = this.byId("table").getBinding("items");
var oContext = oListBinding.create({
Name: "New Product",
Price: 150
});
// Save
oContext.created().then(function() {
MessageToast.show("Product created");
});
Updating:
var oContext = this.byId("table").getSelectedItem().getBindingContext();
oContext.setProperty("Price", 200);
// Save changes
oContext.getModel().submitBatch("$auto").then(function() {
MessageToast.show("Updated");
});
Deleting:
var oContext = this.byId("table").getSelectedItem().getBindingContext();
oContext.delete("$auto").then(function() {
MessageToast.show("Deleted");
});
Documentation: https://github.com/SAP-docs/sapui5/tree/main/docs/04_Essentials (search: odata-v4-model)
Resource Model (i18n)
Model for internationalization texts.
Setup:
// In manifest.json
{
"sap.ui5": {
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"settings": {
"bundleName": "com.mycompany.myapp.i18n.i18n",
"supportedLocales": ["en", "de", "fr"],
"fallbackLocale": "en"
}
}
}
}
}
i18n.properties:
appTitle=My Application
appDescription=A sample SAPUI5 application
# Buttons
btnSave=Save
btnCancel=Cancel
btnDelete=Delete
# Messages
msgSaveSuccess=Data saved successfully
msgDeleteConfirm=Do you want to delete this item?
# Placeholders with parameters
msgItemCount=You have {0} items selected
msgWelcome=Welcome, {0}!
Usage in XML:
<Page title="{i18n>appTitle}">
<Button text="{i18n>btnSave}" press=".onSave"/>
<Text text="{i18n>appDescription}"/>
</Page>
Usage in Controller:
var oBundle = this.getView().getModel("i18n").getResourceBundle();
var sTitle = oBundle.getText("appTitle");
// With parameters
var sMessage = oBundle.getText("msgItemCount", [5]);
MessageBox.success(sMessage);
Locale Files:
i18n.properties: Default (fallback)i18n_de.properties: Germani18n_en.properties: Englishi18n_fr.properties: French
Documentation: https://github.com/SAP-docs/sapui5/tree/main/docs/04_Essentials (search: resource-model, i18n)
XML Model
Client-side model for XML data structures.
Creation:
var oModel = new XMLModel();
oModel.loadData("model/data.xml");
this.getView().setModel(oModel, "xml");
Usage:
<List items="{xml>/products/product}">
<StandardListItem
title="{xml>name}"
description="{xml>price}"/>
</List>
Use Cases:
- Legacy XML data sources
- Configuration files
- Small datasets
Documentation: https://github.com/SAP-docs/sapui5/tree/main/docs/04_Essentials (search: xml-model)
Binding Syntax
Property Binding
Simple Binding:
<Text text="{/companyName}"/>
<Input value="{/employeeName}"/>
Named Models:
<Text text="{invoice>/company/name}"/>
<Input value="{customer>/email}"/>
Binding Options:
<Text text="{
path: '/price',
type: 'sap.ui.model.type.Currency',
formatOptions: {
showMeasure: false
},
constraints: {
minimum: 0
}
}"/>
Composite Binding:
<Text text="{
parts: [
{path: '/firstName'},
{path: '/lastName'}
],
formatter: '.formatFullName'
}"/>
Controller:
formatFullName: function(sFirstName, sLastName) {
return sFirstName + " " + sLastName;
}
Aggregation Binding
List Binding:
<List items="{/products}">
<StandardListItem
title="{name}"
description="{description}"
info="{price} EUR"/>
</List>
Table Binding:
<Table items="{
path: '/products',
sorter: {
path: 'name'
},
filters: {
path: 'price',
operator: 'GT',
value1: 50
}
}">
<columns>
<Column><Text text="Name"/></Column>
<Column><Text text="Price"/></Column>
</columns>
<items>
<ColumnListItem>
<cells>
<Text text="{name}"/>
<Text text="{price}"/>
</cells>
</ColumnListItem>
</items>
</Table>
With Parameters:
<Table items="{
path: '/Products',
parameters: {
expand: 'Category',
select: 'ID,Name,Price'
}
}">
Element Binding
Sets binding context for entire control:
<Panel binding="{/selectedProduct}">
<VBox>
<Text text="{name}"/>
<Text text="{description}"/>
<Text text="{price} EUR"/>
</VBox>
</Panel>
// In controller
onProductSelect: function(oEvent) {
var oItem = oEvent.getParameter("listItem");
var sPath = oItem.getBindingContext().getPath();
this.byId("detailPanel").bindElement({
path: sPath,
parameters: {
expand: "Category"
}
});
}
Expression Binding
Inline calculations without formatter:
<!-- Conditional text color -->
<Text
text="{price}"
color="{= ${price} > 100 ? 'red' : 'green'}"/>
<!-- Conditional visibility -->
<Button
visible="{= ${status} === 'approved'}"
text="Process"/>
<!-- Calculations -->
<Text text="{= ${quantity} * ${price}}"/>
<!-- String operations -->
<Text text="{= ${firstName} + ' ' + ${lastName}}"/>
<!-- Comparisons -->
<Button enabled="{= ${quantity} > 0 && ${stock} >= ${quantity}}"/>
Supported Operations:
- Arithmetic:
+,-,*,/,% - Comparison:
===,!==,>,<,>=,<= - Logical:
&&,||,! - Ternary:
condition ? true : false - String concatenation:
+
Limitations:
- Simple expressions only
- No function calls
- Use formatters for complex logic
Formatters & Data Types
Custom Formatters
Definition:
// In controller or separate formatter.js
formatPrice: function(sPrice) {
if (!sPrice) return "";
return parseFloat(sPrice).toFixed(2) + " EUR";
},
formatStatus: function(sStatus) {
var mStatusText = {
"A": "Approved",
"R": "Rejected",
"P": "Pending"
};
return mStatusText[sStatus] || sStatus;
},
formatDate: function(oDate) {
if (!oDate) return "";
var oDateFormat = sap.ui.core.format.DateFormat.getDateInstance({
pattern: "dd.MM.yyyy"
});
return oDateFormat.format(oDate);
}
Usage:
<Text text="{path: 'price', formatter: '.formatPrice'}"/>
<Text text="{path: 'status', formatter: '.formatStatus'}"/>
<Text text="{path: 'createdAt', formatter: '.formatDate'}"/>
Multiple Parameters:
<Text text="{
parts: ['quantity', 'price'],
formatter: '.formatTotal'
}"/>
formatTotal: function(iQuantity, fPrice) {
return (iQuantity * fPrice).toFixed(2) + " EUR";
}
Built-in Data Types
String Type:
<Input value="{
path: '/name',
type: 'sap.ui.model.type.String',
constraints: {
maxLength: 50,
minLength: 2
}
}"/>
Integer Type:
<Input value="{
path: '/quantity',
type: 'sap.ui.model.type.Integer',
constraints: {
minimum: 1,
maximum: 999
}
}"/>
Float Type:
<Input value="{
path: '/price',
type: 'sap.ui.model.type.Float',
constraints: {
minimum: 0,
maximum: 99999.99
},
formatOptions: {
minFractionDigits: 2,
maxFractionDigits: 2
}
}"/>
Date Type:
<DatePicker value="{
path: '/orderDate',
type: 'sap.ui.model.type.Date',
formatOptions: {
pattern: 'dd.MM.yyyy'
}
}"/>
DateTime Type:
<DateTimePicker value="{
path: '/createdAt',
type: 'sap.ui.model.type.DateTime',
formatOptions: {
pattern: 'dd.MM.yyyy HH:mm:ss'
}
}"/>
Currency Type:
<Text text="{
parts: [
{path: 'price'},
{path: 'currency'}
],
type: 'sap.ui.model.type.Currency',
formatOptions: {
showMeasure: true
}
}"/>
Boolean Type:
<CheckBox selected="{
path: '/isActive',
type: 'sap.ui.model.type.Boolean'
}"/>
Filters & Sorters
Filters
Simple Filter:
var oFilter = new Filter("price", FilterOperator.GT, 100);
var oBinding = this.byId("table").getBinding("items");
oBinding.filter([oFilter]);
Multiple Filters (AND):
var aFilters = [
new Filter("price", FilterOperator.GT, 100),
new Filter("category", FilterOperator.EQ, "Electronics")
];
oBinding.filter(aFilters); // AND condition
Multiple Filters (OR):
var aFilters = [
new Filter("status", FilterOperator.EQ, "Approved"),
new Filter("status", FilterOperator.EQ, "Pending")
];
var oCombinedFilter = new Filter({
filters: aFilters,
and: false // OR condition
});
oBinding.filter([oCombinedFilter]);
Complex Filters:
var oPriceFilter = new Filter({
filters: [
new Filter("price", FilterOperator.GT, 100),
new Filter("price", FilterOperator.LT, 500)
],
and: true
});
var oStatusFilter = new Filter({
filters: [
new Filter("status", FilterOperator.EQ, "A"),
new Filter("status", FilterOperator.EQ, "P")
],
and: false
});
var oCombinedFilter = new Filter({
filters: [oPriceFilter, oStatusFilter],
and: true
});
oBinding.filter([oCombinedFilter]);
Filter Operators:
EQ: EqualsNE: Not equalsGT: Greater thanGE: Greater or equalLT: Less thanLE: Less or equalContains: Contains textStartsWith: Starts with textEndsWith: Ends with textBT: Between (requires value1 and value2)
Custom Filter Function:
var oFilter = new Filter({
path: "price",
test: function(oValue) {
return oValue > 100 && oValue < 500;
}
});
Sorters
Simple Sort:
var oSorter = new Sorter("name", false); // false = ascending
var oBinding = this.byId("table").getBinding("items");
oBinding.sort(oSorter);
Multiple Sorters:
var aSorters = [
new Sorter("category", false),
new Sorter("price", true) // true = descending
];
oBinding.sort(aSorters);
Sort with Grouping:
var oSorter = new Sorter("category", false, true); // third param = group
oBinding.sort(oSorter);
Custom Group Function:
var oSorter = new Sorter("price", false, function(oContext) {
var fPrice = oContext.getProperty("price");
if (fPrice < 100) return { key: "low", text: "Low Price" };
if (fPrice < 500) return { key: "medium", text: "Medium Price" };
return { key: "high", text: "High Price" };
});
Links to Official Documentation
- Data Binding: https://github.com/SAP-docs/sapui5/tree/main/docs/04_Essentials (search: data-binding)
- Models: https://github.com/SAP-docs/sapui5/tree/main/docs/04_Essentials (search: model)
- OData: https://github.com/SAP-docs/sapui5/tree/main/docs/04_Essentials (search: odata)
- Get Started Tutorials: https://github.com/SAP-docs/sapui5/tree/main/docs/03_Get-Started
- API Reference: https://sapui5.hana.ondemand.com/#/api
Note: This document covers data binding and model usage in SAPUI5. For specific implementation details and advanced scenarios, refer to the official documentation links provided.