Skip to Content

Hi All


Since the first release of SAPUI5 I started trying to use it with JSON and I did not find a way to pass callback functions to the loadData method of the JSON Model. While reading the SAPUI5 documentation I found two methods that can be used to attach handlers to the request completed and request failed events, but to be honest I didn’t find it useful. So I decided to post a thread in the SCN forum.

After few weeks without answers I decided to take a look under the hood. When I opened the JSONModel.js file I saw where the loadData method calls the jQuery.ajax and I finally found what I was looking for, i.e., what I need to change to meet my requirements.

Capture1BlogExtendJSONModel.JPG

Figure 1 – JSON Model source code

Now that I knew what needed to be changed in the loadData method to received the callback functions as parameters the next question was: how to extend the JSON Model? Turning back to the SAPUI5 documentation I found the extend method which enables, as it’s name says, to extend the JSON Model.

Sharing the results

myJSONModel.js file with the JSON Model extension

How it was extended: a new method was declared (loadDataNew). Two new parameters (fnSuccess and fnError) were added to the method and the callback functions calls were inserted (see source code comments).

jQuery.sap.require("sap.ui.model.json.JSONModel");
sap.ui.model.json.JSONModel.extend("myJSONModel", {
          //declare our new method including two new parameters fnSuccess and fnError, our callback functions
          loadDataNew: function(sURL, fnSuccess, fnError, oParameters, bAsync, sType, bMerge, bCache){
                              var that = this;
                              if (bAsync !== false) {
                                        bAsync = true;
                              }
                              if (!sType)          {
                                        sType = "GET";
                              }
                              if (bCache === undefined) {
                                        bCache = this.bCache;
                              }
                              this.fireRequestSent({url : sURL, type : sType, async : bAsync, info : "cache="+bCache+";bMerge=" + bMerge});
                              jQuery.ajax({
                                url: sURL,
                                async: bAsync,
                                dataType: 'json',
                                cache: bCache,
                                data: oParameters,
                                type: sType,
                                success: function(oData) {
                                        if (!oData) {
                                                  jQuery.sap.log.fatal("The following problem occurred: No data was retrieved by service: " + sURL);
                                        }
                                        that.setData(oData, bMerge);
                                        that.fireRequestCompleted({url : sURL, type : sType, async : bAsync, info : "cache=false;bMerge=" + bMerge});
                                        // call the callback success function if informed
                                        if (typeof fnSuccess === 'function') {
                                             fnSuccess(oData);
                                         }
                                },
                                error: function(XMLHttpRequest, textStatus, errorThrown){
                                        jQuery.sap.log.fatal("The following problem occurred: " + textStatus, XMLHttpRequest.responseText + ","
                                                                      + XMLHttpRequest.status + "," + XMLHttpRequest.statusText);
                                        that.fireRequestCompleted({url : sURL, type : sType, async : bAsync, info : "cache=false;bMerge=" + bMerge});
                                        that.fireRequestFailed({message : textStatus,
                                                  statusCode : XMLHttpRequest.status, statusText : XMLHttpRequest.statusText, responseText : XMLHttpRequest.responseText});
                                         // call the callback error function if informed
                                        if (typeof fnError === 'function') {
                                             fnError({message : textStatus, statusCode : XMLHttpRequest.status, statusText : XMLHttpRequest.statusText, responseText : XMLHttpRequest.responseText});
                                         }
                                }
                              });
          }
});

and below is the code implemented in the index.html to exemplify its use


<!DOCTYPE html> 
<html><head> 
    <meta http-equiv='X-UA-Compatible' content='IE=edge' /> 
    <title>Extending the JSON Model</title> 
    <style>
        #firstname, #lastname, #btn1, #btn2, #btn3 { margin: 0 4px; }
        #content{ margin-top: 10px; }
    </style>
    <script id='sap-ui-bootstrap' type='text/javascript' 
        src='../../sapui5/resources/sap-ui-core.js' 
        data-sap-ui-theme='sap_goldreflection' 
        data-sap-ui-libs='sap.ui.commons'></script>  
    <script type='text/javascript' src='myJSONModel.js'></script>    
    <script> 
        //callback function for successful requests
       function request_success (oData) {
            if(oData.success){
                sap.ui.commons.MessageBox.alert('Data loaded successfully');
            }else{
                sap.ui.commons.MessageBox.alert(oData.msg);
            }
        }
        //callback function to handle communication errors
        function request_error () {
                  sap.ui.commons.MessageBox.alert(arguments[0].statusText);
        }
        //create the ApplicationHeader control
        var oAH = new sap.ui.commons.ApplicationHeader('appHeader', {
            logoSrc: 'http://www.sap.com/global/images/SAPLogo.gif',
            logoText: 'SAP SAPUI5 Library',
            displayLogoff: false
        });
        //create the label for field First name
        var oL1 = new sap.ui.commons.Label('l1', {
            text: 'First name:'
        });
                //create the label for field Last name
        var oL2 = new sap.ui.commons.Label('l2', {
            text: 'Last name:'
        });
        //create Input field First name
        var oTF1 = new sap.ui.commons.TextField('firstname', {
            value: '{/data/firstname}'
        });
        //create Input field Last name
        var oTF2 = new sap.ui.commons.TextField('lastname', {
            value: '{/data/lastname}'
        });
        //create our custom model
        var oModel = new myJSONModel;
        //set our model
        oTF1.setModel(oModel);
        oTF2.setModel(oModel);
        //create button to load data from server
        var oBtn1 = new sap.ui.commons.Button('btn1',{ 
            text:'Load data (ok)', 
            press:function(){
                oModel.loadDataNew("data_success.json", request_success, request_error);
            } 
        });
         //create button to load data from server
        var oBtn2 = new sap.ui.commons.Button('btn2',{ 
            text:'Load data (user not found)', 
            press:function(){
                oModel.loadDataNew("data_error.json", request_success, request_error);
            } 
        });
        //create button to load data from server
        var oBtn3 = new sap.ui.commons.Button('btn3',{ 
            text:'Load data (file not found error)', 
            press:function(){
                oModel.loadDataNew("filenotfound.json", request_success, request_error);
            } 
        }); 
        //create the layout
                var oLayout = new sap.ui.commons.layout.HorizontalLayout("Layout1", {
            content: [oL1, oTF1, oL2, oTF2, oBtn1, oBtn2, oBtn3]
        });
        //place our controls
        oAH.placeAt("appheader");
        oLayout.placeAt("content");
    </script>
</head>
<body class='sapUiBody'>
    <div id='appheader'></div>
    <div id='content'></div>
</body>
</html>

Screenshots

Capture2BlogExtendJSONModel.JPG

Figure 2 – Initial screen

Capture3BlogExtendJSONModel.JPG

Figure 3 – Success callback function called with results

Capture4BlogExtendJSONModel.JPG

Figure 4 – Success callback function called with no results


Capture5BlogExtendJSONModel.JPG

Figure 5 – Error callback function called (simulating a communication error)

The eclipse project with the complete source code can be downloaded from the url below.

http://jianelli.com.br/sap/scnblog1.zip

Your feedback is most welcome!

Christian Jianelli


To report this post you need to login first.

7 Comments

You must be Logged on to comment or reply to a post.

  1. Onno Bos

    Dear Christian,

    Why don’t you set the standard SAP event on the model.

    var oModel = new myJSONModel;

    oModel.fireRequestCompleted(

        function () {

            alert(“You Request completed”);

        }

    );

    Kind regards,

    Onno Bos

    (0) 
    1. Christian Jianelli Post author

      Hi Onno,

      The documentation says that this method fires the event to attached listeners and the purpose of the extension is to provide an easy way to attach listeners, not fire the events.

      fireRequestCompleted(mArguments?) : sap.ui.model.Model

           Fire event requestCompleted to attached listeners.

      Best regards,

      Christian

      (0) 
        1. Christian Jianelli Post author

          Hi Onno,

          As said in the first paragraph I tried to use the attachRequestCompleted and the attachRequestFailed but i didn’t find it useful. One of the reasons is that the request failed event also calls the request completed listener, but without any information indicating that an error ocurred and it is called before the request failed listener.

          Best regards,

          Christian

          (0) 
          1. Jan Müller

            Hi Christian,

            while I was working on my Application I noticed the same thing about the request failed and request completed listener.

            Do you know, if the calling of the request completed listener before the request failed listener is considered a bug or was it intentionally made this way?

            You said above that this was only one of the reasons why you didn’t find it useful. What are the other reasons ?

            Kind regards,

            Jan

            (0) 
            1. Christian Jianelli Post author

              Hi Jan,

              I’m not sure if it is a bug or not. I think it’s not.

              If you compare the JSONModel with the oDataModel you will see that the oDataModel have a “change control” and many other features that the JSONModel does not have. That is the main reason why I think it is not very useful.

              Regards,

              Christian

              (0) 

Leave a Reply