My First Example Of Using OData V4 Model
With SAPUI5 version 1.37 the sap.ui.model.odata.v4.ODataModel finally got released. First of all please note that it’s still under construction, therefore you should definitely not use it for productive applications. Furthermore: The code I’m providing is just a quick example and sometimes kind of antipattern (e.g. there are only very few use cases where you should call sap.ui.getCore()).
I didn’t examine the source code yet and read just the API documentation from sap.ui.model.odata.v4.ODataModel. So please be welcomed to correct me if any of my statements or conclusions are wrong.
The first things I noticed are that there are much less constructor properties than in V2 and that many methods are marked as “not implemented yet”.
Furthermore I noticed that methods I often used in V2 don’t appear at all (create, update, read, remove, …). I guess those operations are triggered automatically by changing the binding (that’s at least the case for update in my example). I hope that the missing methods will be implemented within the next releases anyway, because I think the developers will need them. For example in case you need to create an entity which is not associated with a control.
You can find a working live example in my jsbin. Please note that you’ll have to turn off your browser web security to get it workable, because I’m using a public dummy OData service which doesn’t provide a valid https certificate. You also can download the attached files “ODATAV4-UI5-Sample.html.txt” and “ODATAV4-UI5-Sample.js.txt”, remove the .txt extension (damn SCN file type restrictions), put them in the same location and open “ODATAV4-UI5-Sample.html” in your browser. In that case you won’t have to turn off your browser security.
In my example I’ve created two models: One with activated batch mode and the other in direct mode. Next I’ve created two lists and two input fields which are bound to the models. If you select an item from the list the input field will show the property “Gender”. As soon as you change the value and leave the field a patch request will be triggered to update the backend service. Here’s what it looks like in all its ugly simpleness:
OK, hands on!
Let us have a deeper look at the constructor. Note: It seems not possible yet that you can change between batch and direct mode later. That’s why you’ll have to decide that at the beginning with the parameter “groupId”.
Anyway here’s an example for a new model in direct mode:
var oModel = new sap.ui.model.odata.v4.ODataModel({
/* send requests directly. Use $auto for batch request wich will be send automatically on before rendering */
groupId : "$direct",
/* I'll just quote the API documentary:
Controls synchronization between different bindings which refer to the same data for the case data changes in one binding.
Must be set to 'None' which means bindings are not synchronized at all; all other values are not supported and lead to an error.
*/
synchronizationMode : "None",
/*
Root URL of the service to request data from.
*/
serviceUrl : "http://services.odata.org/TripPinRESTierService/",
/*
optional. Group ID that is used for update requests. If no update group ID is specified, mParameters.groupId is used.:
updateGroupId : "$direct"
*/
});
The next thing to do is to announce the model (~sure, otherwise the controls can’t find them đ ). In my example I’ve just put all my content in a sap.m.Panel, so I called:
var panel = new sap.m.Panel({ /* ... */});
panel.setModel(oModel, "oModel");
Afterwards I created a new List and declared a select function within its constructor (#antipattern):
var list2 = new sap.m.List({
includeItemInSelection : true,
mode : "SingleSelect",
select : function(oEvent){
var input = sap.ui.getCore().byId("changeGender2");
var listBindingContext = oEvent.getParameter("listItem").getBindingContext("oModel");
input.setBindingContext(listBindingContext, "oModel");
input.bindValue({
path : "oModel>Gender",
type: new sap.ui.model.type.String()
});
}
});
Finally I setup the binding for the item aggregation with a sap.m.StandardListItem template which uses property binding for the properties title and description:
list2.bindItems({
path : "oModel>/People",
template : new sap.m.StandardListItem({
title : "{oModel>FirstName} {oModel>LastName}",
description : { path : "oModel>UserName" }
})
That’s it. I hope it will help someone who struggles with OData V4 on SAPUI5, too.
Cheers
#yeahyeah
Since this blog has been published, quite some time has passed. We have added new features to the OpenUI5 / SAPUI5 OData V4 model with each release and also fixed bugs.
Â
Recently the following bug has been reported: If you call the sap.ui.model.odata.v4.Context#getObject() or the sap.ui.model.odata.v4.Context#requestObject() methods without a parameter, the expected and documented behavior is that the same result is returned as if the parameter sPath=ââ had been specified. Due to the bug, however, the return value wraps the expected output which can then only be accessed via .value[0], for example oContext.getObject().value[0].
Â
If you have used this workaround, your application will break starting with OpenUI5 version 1.44.6 / SAPUI5 version 1.44.7.
Â
Solution: If your application needs to run with both, the fixed and unfixed versions of OpenUI5, specify the sPath=ââ parameter, for example oContext.getObject(ââ). If your application runs on OpenUI5 1.44.6 or higher / SAPUI5 1.44.7 or higher, you do not need to specify the sPath parameter. In both cases, you must not use the workaround with .value[0] any longer.
ive tried running the js bin example but it is not showing any data ,
please find attached screenshot
Â
thanks
mukul ahuja
Hi Tim,
thanks for your blog.
I agree that regular CRUD methods should be available. I guess over 90% of the oData calls work via bindings. But there are some rare cases where you have to read some data explicitly from a back-end without binding it against a control. For such calls we have to fall back to oDataV2 then. But it seems like SAP will not offer that in the future:
https://sapui5.hana.ondemand.com/#/topic/abd4d7c7548d4c29ab8364d3904a6d74.html
Tobias
Hi Tobias,
you can also create binding objects in your controller code by using
of sap.ui.model.odata.v4.ODataModel.
Would that solve your problems?
Best regards
Mathias.
Hi Mathias,
I haven't worked with oData V4 in SAPUI5 yet but as far as I know the methods you described are meant to bind some aggregation/property to a control or a control property. I think it is not possible to trigger an oData read request explicitly. In oData V2 you can dome something like:
This is very useful in some scenarios and I think the author of this blog means that this not possible anymore.
Tobias
Hi Tobias,
so far we could resolve all concrete use cases by using the factory methods I mentioned in my previous reply. These methods are public and can be used to create a binding object in controller code. This can be used to read and modify data without binding to a control.
The documentation contains an example related to bound actions and functions in https://sapui5.hana.ondemand.com/#/topic/b54f7895b7594c61a83fa7257fa9d13f.
Using the factory methods it is also possible with the v4.ODataModel to read data without binding to a control.
Best regards
Mathias.
Hi Mathias Uhlmann Mathias Uhlmann
Can you provide an example how to do it? I have this requirement as I have posted a question in this blog.
https://answers.sap.com/questions/12692133/read-and-modify-data-in-odata-v4-before-binding-to.html
Thanks
Hi Don,
I have provided an example in your post https://answers.sap.com/questions/12692133/read-and-modify-data-in-odata-v4-before-binding-to.html.
Best regards
Mathias.