SAPUI5 and OData v1: Ajax call and BusyIndicator
Scenario
In SAP HCP (SAP Hana Cloud Platform), while developing a HTML5 application with sapui5, aiming to make a post to a OData Service, it is good practice to show a loading warning to make sure the user keeps calm and wait for the cloud to do its job. It may seem pretty easy using the BusyIndicator component by showing it in any time. However, since javascript refresh the components only after the function is finished, a ajax call must take place to wrap the oDataModel POST.
The given-free idea
Accordingly to sapui5 documentation, to show the BusyIndicator in any time, we must simply call:
1 | sap.ui.core.BusyIndicator.show(0); |
Well, that works well, but only when the function that wraps this call finish.
So… What if we have an oData call going on and we want to show the BusyIndicator?
Again, as the documentation and various post on the internet point, we could easily build this behavior by coding the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | var serviceUrl1 = "URL1"; var serviceUrl2 = "URL2"; var payload = { name : "some payload" }; var oModel = new sap.ui.model.odata.ODataModel({serviceUrl1: serviceUrl2}); // here we desire to show the indicator. sap.ui.core.BusyIndicator.show(0); oModel.create("/entitySet","POST",payload, null, function(oData, oResponse) { sap.ui.core.BusyIndicator.hide(); //Success Call }, function(oError) { sap.ui.core.BusyIndicator.hide(); //Error Call // true for async }, true); |
With this, we hope that the BusyIndicator will be shown as the request is performed, since it is put as an async call.
Expectation breakdown!
Unfortunately, the BusyIndicator is not shown. Not in my world, at least. However, I managed to workaround wrapping the call into a AJAX request.
The workaround solution
Doing the following, wrapping the oData call into a ajax async call, I managed to get my BusyIndicator to work:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | function(evt) { var that = this; var token = null; var serviceUrl = "URL"; var payload = {}; /* * payload building process omitted */ this.oModel = new sap.ui.model.odata.ODataModel(serviceUrl); sap.ui.getCore().setModel(this.oModel); /* * This is where the magic happens: * 1) ajax async request to get the token and to show the busy indicator on the screen * 2) when it's over, make a post to the oData service with the data. * 3) when it's over, hide the busy indicator and go to the correct page (success or error). */ $.ajax({ url: serviceUrl + "/MyCollection"; type: "GET", async: true, beforeSend: function(xhr) { sap.ui.core.BusyIndicator.show(0); xhr.setRequestHeader("X-CSRF-Token", "Fetch"); }, complete: function(xhr) { // after requesting the token, save this into a variable. // funny thing: we don't use it anywhere, since oData.create // already handles this. However, without this call the OData Service // denies my requests. So, let's stick to this until I find a more // beautiful solution. token = xhr.getResponseHeader("X-CSRF-Token"); // begin of odata send that.oModel.create("/MyCollection", payload, null, function(response){ sap.ui.core.BusyIndicator.hide(); sap.ui.core.UIComponent.getRouterFor(that).navTo("insertConfirmation"); that.clearInputs(); },function(){ sap.ui.core.BusyIndicator.hide(); sap.ui.core.UIComponent.getRouterFor(that).navTo("insertErrorConfirmation"); that.clearInputs(); }); } }); } |
Note that the code is a lot different from the other one. That’s because I didn’t save any efforts to make this to be very detailed 😉
With this, I managed to make the BusyIndicator to work.
Observations about the ajax wrap
A good practice while dealing with OData services from within sapui5 is to use the oDataModel calls, since they already have good managing on POST methods and nice treatment of responses. It is no good to make a ajax call to POST data into OData services. Here, we make an ajax call only to get the CSRF token from the OData service maintaining the async characteristic, and then we POST the data (payload) with the oData.create() call, which is a good practice.
Conclusion
To show the BusyIndicator while making an oData call with sapui5, wrapping the call inside an ajax async call is one possible solution.