Show TOC

OData OperationsLocate this document in the navigation structure

The OData V4 model supports OData operations (ActionImport, FunctionImport and bound Actions). Unbound parameters are limited to primitive values.

Simple Function Bindings
You gain access to a FunctionImport by binding it to a view element. If there are no parameters and there is no need to control the point in time when the function is called, you can simply bind the OData path like this:
<Text text="{/GetNumberOfAvailableItems()}"/>
This binding path represents the function's return value. The model calls the function immediately when a control requests this value.
Deferred Operation Bindings

Often it is not feasible for the operation to be called immediately, for example if there are parameters that the user has to enter first. In such cases, use an ODataContextBinding as element binding at a layout element in the view, for example a <Form> or a <VBox> (see the ODataContextBinding API documentation in the Demo Kit). Mark the operation as deferred by inserting an ellipsis ("...") in the brackets, for example GetNextAvailableItem(...). Access the return value from child elements using relative bindings. When used like this, the context binding is called an operation binding or more specifically, a function binding or action binding depending on the type of OData operation it is used for.

If the operation binding defers operation execution, you need to call its execute method to execute the operation. See below for an example.

View:

<Form id="getNextAvailableItem" binding="{/GetNextAvailableItem(...)}">
    <Label text="Description"/>
    <Text text="{Description}"/>
    <Button text="Call the function" press="onGetNextAvailableItem"/>
</Form>

Controller:

onGetNextAvailableItem : function (oEvent) {
    this.getView().byId("getNextAvailableItem").getObjectBinding().execute();
}

In the above example, the function import is bound to a form (which has an ID that we need later). The text field showing a property of the result is a child of this form. It has a relative binding to the property "Description".

If the function returns a primitive value, the binding for the result must be "{value}" as shown here:

View:

<Form id="getNumberOfAvailableItems" binding="{/GetNumberOfAvailableItems(...)}">
    <Label text="Number of available items:"/>
    <Text text="{value}"/>
    <Button text="Call the function" press="onGetNumberOfAvailableItems"/>
</Form>

execute returns a promise which is resolved if the operation was successful and rejected with an error if this was not the case. Note that the promise is not fufilled with the action's result: Use dependent bindings to access the result.

refresh is silently ignored on a deferred function binding as long as it has not yet been executed. Afterwards, a refresh calls the function again.

Action Bindings

Action bindings must be deferred, otherwise the application cannot control when the action is executed. A deferred action binding is declared exactly like a deferred function binding:

View:

<Form id="Submit" binding="{/Submit(...)}">
    <Button text="Submit the action" press="onSubmit"/>
</Form>

You append "(...)" even though the action's resource URL does not contain them. However, they are needed to mark the binding as deferred. In execute, the binding uses the metadata to distinguish between action and function and to build the correct operation resource path.

refresh is always silently ignored on a deferred action binding to prevent the action from being executed accidentally (for example by calling the refresh method on the ODataModel instance oModel.refresh()).

Operation Parameters

Operation parameters can be set by calling the function setParameter on the operation binding, as shown in this example:

Controller:

onSubmit : function (oEvent) {
    this.getView().byId("Submit").getObjectBinding().setParameter("Comment", sComment).execute();
}
Bound Actions

So far, the examples always used operations at root level, addressed via an action import or function import. However, it is also possible to bind an action to another resource of the service. This can be an entity, a collection of entities or an entity property. In this case, the resource path of the action is a concatenation of the resource path identifying the binding parameter and the fully qualified action name.

Example: Submitting a leave request might be a bound action. The resource path is then /LeaveRequests(ID='42')/name.space.Submit.

Bound actions are controlled in the same way as unbound operations; append (...) to the binding path for the control's property. This means you can bind /LeaveRequests(ID='42')/name.space.Submit(...) to a control and call execute on the resulting context binding to submit this very special leave request. This in itself is not very useful, normally you would like to select a leave request from a list and submit it. This can be achieved with relative bindings, as shown in this example:

<Table binding={/LeaveRequests}>
    <Columns>
        <Column>
            <Text text={name}/>
            <Button id="onSubmit" binding="name.space.Submit(...)"/>
        </Column>
    </Columns>
</Table>

Now the operation binding at the button is relative. There is one for each row of the table having a context for this row's leave request as parent. execute now calculates the resulting path for the request from this context and the relative binding path of the deferred operation. When pressed in the row for the leave request with ID='42', the request path will be /LeaveRequests(ID='42')/name.space.Submit.

Note
  • This also works if the path of the operation binding starts with a navigation property. For example, if the operation is bound to Address/name.space.Change(...) and the parent is a list binding on /BusinessPartners, you call an action bound to the address of the given business partner. The resource path is for example /BusinessPartners(ID='42')/Address/name.space.Change.

  • The parent binding of a deferred operation must not be a deferred operation itself.