Reputation: 1482
In UI5, is it possible to bind a single attribute of a single entity to a control property if your model is an OData? Binding works ok if you bind an aggregation to an entity set but does not seem to work with properties to entities. Say I have an entity set called TestSet
. Each "Test" has attribute Key
and Name
. I'd like to bind the title of a table to the Name
of one of the entities on that set.
What's wrong with the following code?
createContent: function(oController) {
jQuery.sap.require("sap.ui.table.Table");
var oTable = new sap.ui.table.Table({title: "{/TestSet('01')/Name}"});
oTable.setModel(new sap.ui.model.odata.ODataModel("/path/to/root/of/odata/"));
oTable.bindProperty("title", "/TestSet('01')/Name");
return oTable;
},
OData works ok when tested in isolation. /TestSet
returns set of Test entities and /TestSet('01')
returns one of those entities.
I've tested binding to /Name
, /TestSet('01')/Name
, etc. Nothing seems to work.
Upvotes: 2
Views: 10286
Reputation: 18044
According to the developer guide ...
Requests to the back end are triggered by list bindings, element bindings, and CRUD functions provided by the ODataModel. Property bindings do not trigger requests.
Thus, instead of trying to bind data directly on the properties of the target control with an absolute path, leverage ContextBinding
(aka. "Element Binding") on the parent control or on the target control itself, and then bind the data on the properties of the target control or even further on child controls with a relative path (>
instead of >/
in the path).
We can bind a single entity either in JS (e.g. if entity keys are required) or in XML views.
Instead of hardcoding the key predicate of the entity type, make sure to create the binding path together with key(s) via v2.ODataModel.createKey()
dynamically after $metadata
is loaded.
const oTable = new Table({ // Required from "sap/ui/table/Table"
title: "{Name}", // No absolute but relative binding path (no '/')
});
const myODataModel = /*...*/;
await myODataModel.metadataLoaded();
const bindingPath = myODataModel.createKey("/TestSet", { // See stackoverflow/a/47016070
key1: "...",
key2: 1234,
}); // Returns e.g. "/TestSet(key1='test1',key2='1234l')"
oTable.bindElement({ // Triggers a request and resolves the relative {Name} property.
path: bindingPath,
parameters: {
expand: "...",
select: "...",
// ... for more options see sap/ui/model/odata/v2/ODataContextBinding
},
events: { // Event handlers can be also assigned
dataRequested: e => { /*...*/ },
dataReceived: e => { /*...*/ },
change: e => { /*...*/ },
},
});
Note: bindElement
and bindObject
are same APIs just with different names. See also GitHub issue#3000.
In XML views, single object / entity can be bound via binding
in any controls. But creating keys dynamically (with createKey
as shown above) is not possible. Hence, use binding
only in combination with a <NavigationProperty>
name, where keys are not required to be defined.
<table:Table xmlns:table="sap.ui.table"
binding="{
path: 'ToThatSingleEntity',
parameters: {
expand: '...',
select: '...'
},
events: {
dataRequested: '.onDataRequested',
dataReceived: '.onDataReceived',
change: '.onDataFromModelChanged'
}
}"
title="{FromThatSingleEntity}">
binding="{/TestSet(<keys>)}"
is also possible but, again, the keys need to be then hardcoded.
Upvotes: 5
Reputation: 3105
You can effect a property binding like this by binding the control to the specific element (hierarchy, as it were, is aggregation->element->property). So taking your example, you could do this:
var oTable = new sap.ui.table.Table({
title : "{Name}"
});
and then when you do this:
oTable.bindElement("/Products(0)");
the HTTP call is made by the OData model mechanism and the value appears in the table's title property.
Here's a running example, using Northwind.
Upvotes: 4