Bindings are called absolute if their path starts with a forward slash "/"; otherwise they are called relative. Relative bindings are initial meaning that they have no data as long as they have no context. They obtain a context either from a list binding where the context represents an entity for a certain index in an entity collection or from a context binding where the context represents the one entity of the context binding. The binding which created the context is called the parent binding of the relative binding; the relative binding is a child binding of its parent binding. Dependent bindings of a binding are the set of child bindings of the binding itself and the dependent bindings of its children. If the binding has no child bindings, it is the empty set.
An absolute binding creates a data service request to read data once data is requested by a bound control or a child control with a relative binding. The read URL path is the model's service URL concatenated with the binding's path. The read URL query options are the union of the binding's and model query options; query options specified for the binding overwrite model query options.
For the absolute property bindings of singletons, see Absolute Property Bindings of Singletons.
A relative list or context binding creates a data service request once it has a context in the following cases:
-
The relative binding has parameters, such as OData query options like
$select
, or binding-specific parameters with a name starting with$$
; for more information, see Parameters. If you want a relative binding to create its own data service request, use the binding-specific parameter$$ownRequest
. -
You specify a dynamic filter or dynamic sorter for a list binding and use
sap.ui.model.odata.OperationMode.Server
, see sections Filtering and Sorting.
If the model is configured to compute
$expand
and$select
automatically, this behaviour changes, see Automatic determination of $expand and $select.
A relative property binding never creates a data service request; its binding parameters are ignored in this case.
In all other cases, a relative binding reads data from its parent binding that created the context. In case of an own data service request, the read URL path is the model's service URL concatenated with the path of the binding's context and the binding's path. Set the binding-specific parameter $$canonicalPath
to true
to use the canonical path computed from the context's path instead of the context's path in the read URL.
The point in time that is used to actually send the request is determined as explained in the section Batch Control. Bindings which create own data service requests cache data from data service responses. They do not send a data service request if data can be served from this cache.
List bindings read data in pages, i.e. they only access a certain index range from their bound collection; they only initiate a new data service request if indexes are accessed which have not yet been read.
You can delete the cache for an absolute binding using its refresh
method. The method also deletes the caches of child bindings of the absolute binding.
There must be no pending property changes for a binding and its child bindings when calling the
refresh
method. Use the binding'shasPendingChanges
method to check for pending changes before you delete the cache. To reset pending changes, usesap.ui.model.odata.v4.ODataModel#resetChanges
,sap.ui.model.odata.v4.ODataListBinding#resetChanges
,sap.ui.model.odata.v4.ODataContextBinding#resetChanges
, orsap.ui.model.odata.v4.Context#resetChanges
. To get rid of a transient entity you can usesap.ui.model.odata.v4.Context#delete
.
You can refresh all bindings with ODataModel.refresh
, see ODataModel.refresh in the Demo Kit.
You can refresh a single entity by calling sap.ui.model.odata.v4.Context#refresh
or the bound context or return value context of an sap.ui.model.odata.v4.ODataListBinding
which corresponds to this entity. This also refreshes all dependent bindings of its contexts.
Usage of Context#refresh for a context in a list binding
onRefreshSelectedSalesOrder : function () { // within a sap.m.Table bound to a OData V4 list binding get the OData V4 context for the selected entity var oSalesOrderContext = this.byId("SalesOrders").getSelectedItem().getBindingContext(); if (!oSalesOrderContext.hasPendingChanges()) { oSalesOrderContext.refresh(); } },
Contexts of an
sap.ui.model.odata.v4.ODataListBinding
and the bound context of ansap.ui.model.odata.v4.ODataContextBinding
can only be refreshed if the binding is not relative to ansap.ui.model.odata.v4.Context
.Refresh is only allowed if there are no pending changes for the context and all its dependent bindings. If you have a relative binding with changes and this binding loses its context, the former parent binding does not report pending changes: the changes are kept, but the relation between these bindings is lost. You can do the following:
To find out if there are pending changes, use
sap.ui.model.odata.v4.ODataModel#hasPendingChanges
.To save the changes, use
sap.ui.model.odata.v4.ODataModel#submitBatch
; to reset the changes, usesap.ui.model.odata.v4.ODataModel#resetChanges
,sap.ui.model.odata.v4.ODataListBinding#resetChanges
,sap.ui.model.odata.v4.ODataContextBinding#resetChanges
, orsap.ui.model.odata.v4.Context#resetChanges
. To get rid of a transient entity you can usesap.ui.model.odata.v4.Context#delete
.If you set a context at the relative binding, the new parent binding will report the pending changes again.
After updating an entity, it may no longer match the query options for the collection which loaded the entity, in particular $filter
. You can decide whether the refresh on the context of a list binding should ignore the query options or not: The corresponding context may be removed from the list binding for the collection by setting the parameter bAllowRemoval
to true
.
Note that changes to the list like a different sort order require a refresh of the whole list.
An example can be seen in the SalesOrders application. The table has a filter applied to show only the sales orders with Life Cycle Status = "New". When confirming a sales order, its status will change to In Process and does not match the filter anymore. This sales order is then refreshed and will be removed from the list as the bAllowRemoval
flag is set to true
. This is shown in the following code snippet:
refresh with allow removal
oAction.invoke("confirmSalesOrderActionGroup").then(function () { oConfirmedSalesOrderContext.refresh(undefined, true); // bAllowRemoval = true });
For details, see ODataListBinding.refresh, ODataContextBinding.refresh and ODataPropertyBinding.refresh in the Demo Kit.
Example: Absolute and relative bindings created by an XML view
<Table items="{
path : '/SalesOrderList',
parameters : {
$expand : 'SO_2_BP',
$select : 'BuyerName,CurrencyCode,GrossAmount,Note,SalesOrderID'
}}">
...
<items>
<ColumnListItem>
<cells>
<Text text="{SalesOrderID}"/>
<Text text="{SO_2_BP/CompanyName}"/>
<Text text="{BillingStatus}"/>
</cells>
</ColumnListItem>
</items>
</Table>
<Table items="{
path : 'SO_2_SOITEM',
parameters : {
$select: "DeliveryDate,GrossAmount,SalesOrderID"
}
>
...
</Table>
The above sample shows an absolute list binding: A table's items
aggregation is bound to /SalesOrderList
using the $expand
and $select
query options as binding parameters. The columns define relative bindings with paths SalesOrderID
, SO_2_BP/CompanyName
, and BillingStatus
with the absolute list binding as parent binding.
The
BillingStatus
remains empty and logs an error to the browser console as this structural property is not part of the$select
specified for the list binding.
The lower table for the line items has a relative binding. As it has parameters defined, it initiates its own data service request once it receives its binding context.
You can use ##
in a property binding's path to branch from data into metadata.
Example: Determine label from the corresponding annotation for property GrossAmount
<SimpleForm binding="{/SalesOrderList('42')}">
<Label text="{GrossAmount##@com.sap.vocabularies.Common.v1.Label}" />
<Text text="{GrossAmount}" />
</SimpleForm>
For details, see sap.ui.model.odata.v4.ODataModel#bindProperty
.
A property binding can have an object value if the target type specified in the corresponding control property's binding info is "any" and the binding is relative or points to metadata. The binding's mode has to be OneTime
, see sap.ui.model.BindingMode, unless the binding is for an action advertisement.
A OneWay
binding mode is also supported for relative read-only data (not metadata!) bindings to complex types and collections thereof; for entity types, use a context binding instead.
Example: Using the controller method 'formatPhoneNumbersAsCSV'
to show a comma-separated list of phone numbers for business partner contacts
<SimpleForm binding="{/BusinessPartnerList('42')}">
<Label text="Phone number list" />
<Text text="{path : 'BP_2_CONTACT', mode : 'OneTime', targetType : 'any', formatter : '.formatPhoneNumbersAsCSV'}" />
</SimpleForm>
For details, see sap.ui.model.odata.v4.ODataModel#bindProperty
.
A property binding can target an array element inside a collection of primitive type via a hard-coded index. For a use case, see Geography And Geometry Types. In general, such a binding needs to be read-only, for example, because it belongs to a text control, involves a formatter function, or is an expression binding. There is no need to explicitly set its binding mode to OneTime
or OneWay
(see sap.ui.model.BindingMode
). Both auto-$expand/$select
as well as automatic Type Determination are supported.
You can also address the entire array, for example within an Expression Binding like "{= JSON.stringify(%{coordinates}) }", but you need to take care to avoid automatic Type Determination in this case.
Binding to an array (element)
<FlexBox binding="{/Person('42')/Address/GeoLocation}"> <Text id="coordinates" text="{= JSON.stringify(%{coordinates}) }"/> <Text id="longitude" text="{coordinates/0}"/> <Text id="latitude" text="{coordinates/1}"/> </FlexBox>
Editing properties of an entity sometimes causes side effects on other properties within the same or a related entity. Normally, a PATCH
request which sends the user's input to the server includes side effects for the same entity (if relevant for the UI) within its response. Sometimes, however, an application needs more control on how and when this happens, or needs side effects on related entities as well.
You can use sap.ui.model.odata.v4.Context#requestSideEffects to load side effects. This method can be called on the bound context of a context binding, a row context of a list binding, the header context of a list binding, or on the return value context of an operation binding. Collection-valued navigation properties are fully supported, so an efficient request is sent instead of a simple refresh. The validateFieldGroup
event provides a suitable point in time to request side effects after a certain group of fields has been changed. Using the validateFieldGroup
event allows to initiate the side effect request early enough, so that it is sent in the same batch request as the PATCH
request. For more information, see Field Groups. The API strikes a balance between the generic annotation-based use and specific hard-coded uses. The TargetEntities
and TargetProperties
of the com.sap.vocabularies.Common.v1.SideEffects
annotation can be used directly as input for sap.ui.model.odata.v4.Context#requestSideEffects
. Note that the OData V4 model does not evaluate the SourceEntities
andSourceProperties
of the com.sap.vocabularies.Common.v1.SideEffects
annotation. When requested from the OData V4 meta model, the annotation value looks as follows:
{
"SourceEntities" : [{
"$NavigationPropertyPath" : ""
}, ...],
"SourceProperties" : [{
"$PropertyPath" : "Name"
}, ...],
"TargetEntities" : [{
"$NavigationPropertyPath" : "DraftAdministrativeData"
}, ...],
"TargetProperties" : ["DraftAdministrativeData/*", ...]
}
Consider using the binding-specific $$patchWithoutSideEffects
parameter when using sap.ui.model.odata.v4.Context#requestSideEffects
. This parameter may be used to prevent the implicit loading of side effects with the PATCH
response, see e.g. sap.ui.model.odata.v4.ODataModel#bindContext. It can be set on context bindings and list bindings. If the parameter is not specified in a relative binding, the parameter value from the parent binding is used.
The sap.ui.model.odata.v4.Context#requestSideEffects
API requires a single array as parameter, namely the concatenation of TargetEntities
and TargetProperties
.
The OData V4 model automatically determines the system query options $top
and $skip
based on the data range requested by the control or the application. In the example below, the resulting first request is GET People('angelhuffman')/Friends?$expand=Friends&$skip=0&$top=107
. The value for $top
is calculated from the length of the requested data (7) plus the prefetch size provided by the control (100). Note that adding $top
and$skip
for a nested collection is not supported.
<table:Table id="PeopleTable" width="auto" title="People" visibleRowCount="7"
rows="{
path:'/People(\'angelhuffman\')/Friends',
parameters: {
$expand:'Friends'
}
}">
<table:columns>
...
</table:columns>
</table:Table>
An additional paging mechanism is Server-Driven Paging, for which the server returns only a part of the requested data in order to limit the response size. This mechanism is supported by the OData V4 model since SAPUI5 1.72. The model will provide the data retrieved with the response to the control or application. A follow-up request is not initiated automatically but only once the control or application request additional data from the model.