1
votes

I am building a new SAPUI5 application without pursuing any template approach. What I'm building is just a little form with two fields and a button. AHHhh... "the button".

What about the button? The button has the following code:

<Button text="OK" width="100%" id="__button1" press="insertIntoOData"/>

With that, I expect that when I press the button, the insertIntoOData function is called. And guess what!? It is!

Fantastic!

But the problem is that in the insertIntoOData I want it to show a dialog (which is built with a fragment - check this link) while the OData model handles the insertion of a record. Unfortunately, I haven't managed to get the dialog to be shown. It looks like the insertIntoOData function is called synchronously, and won't show the dialog until the function is done.

When the OData Model finish handling the insertion, a response is processed and the dialog is shown only for a moment because, as you may notice in the following code of insertIntoOData, the navigation is redirected to the master (main) page.

insertIntoOData: function(evt) {

    /* 
    * to prevent namespace issues, reserve 'this' into 'that',
    * so the ajax will know who to call inside its scope
    */
    var that = this;

    //declare the dialog
    if (!that._dialog) {
        that._dialog = sap.ui.xmlfragment("valac.view.requestloading", null);
        that.getView().addDependent(that._dialog);
    }

    // open dialog
    jQuery.sap.syncStyleClass("sapUiSizeCompact", that.getView(), that._dialog);
    that._dialog.open();


    // get the csrf token from the service url
    var csrfToken = this.getCSRFToken("/valacDestination/sap/c4c/odata/v1/c4codata/ValacObjectCollection");

    // get the values from the 'form'
    var name_var = this.byId("tSubjectInput").getValue();
    var description_var = this.byId("tDescriptionArea").getValue();

    // create the entry that will be sent with the request
    var oEntry = {};

    // the description list
    oEntry.requestDescription = [];

    // the description item that goes inside the list
    var entryOfRequestDescription = {};
    entryOfRequestDescription.Text = description_var;
    oEntry.requestDescription.push(entryOfRequestDescription);

    // name is a complex object that needs to be built. Content and language.
    oEntry.Name = {};
    oEntry.Name.content = name_var;
    oEntry.Name.languageCode = "EN";

    // fetch the model schema
    var oModel = new sap.ui.model.odata.ODataModel("/valacDestination/sap/c4c/odata/v1/c4codata/");

    sap.ui.getCore().setModel(oModel);

    /* create the entry into the model schema via ajax
    * return to the master page if there's a success response
    * put a message on the master page.
    */
    oModel.create('/ValacObjectCollection', oEntry, null, function(response){
        that._dialog.close();
        sap.ui.core.UIComponent.getRouterFor(that).navTo("master");     
        sap.m.MessageToast.show("Object Persisted!", {
            duration: 30000000
        });
    },function(){
        that._dialog.close();
        sap.m.MessageToast.show("ERROR!", {
            duration: 30000000
        });
    });
}

My question is: How can I show the dialog before the insertIntoOData ends or calls the oModel.create function?

3
Well if your request is handled very fast, does it really make sense to show a dialog? Views (and controls) have the property busy which might be more suitable in your case.Marc
Hi @Valak, make the odata request asyncronous. Create request is synchronous by default and hence browser is waiting for response to arrive and then work ahead. Hence, once the response comes back, it opens the popup but then next line says: close the popup. Hence, you see popup for second. TL;DR: JS is single threaded language. Use async property of oData.create and check.Rahul Bhardwaj
@Marc: the request is very slow, that's why I want the loading thing. The busy property of the view does not do anything too.Valac
@RahulBhardwaj: thanks for your answer. I already checked that out since the oData.create is async by default. I tried the approach to explicit the async property. Nothing happened. All stays the same.Valac
@Valac: in odata.create is async by default is false. Can you please update the code so we are on same page. async : true has to be set.Rahul Bhardwaj

3 Answers

0
votes

when you enter the insertIntoOData method. before calling the service set

  that._dialog.setBusy(true);

after getting service responce (sucess or error don't matter )set as

that._dialog.setBusy(false);
0
votes

You can do global busy indicator or component busy indicator, show before oModel.create and hide into the success or error function:

sap.ui.core.BusyIndicator.show(0); <- Parameter is delay time.

sap.ui.core.BusyIndicator.hide();  <- hide

link docs: https://sapui5.hana.ondemand.com/1.44.18/explored.html#/sample/sap.ui.core.sample.BusyIndicator/preview

Only the Dialog show busy.

that._dialog.setBusy(true); <- Show

that._dialog.setBusy(false); <- hide
0
votes

I've managed to show the busyIndicator. I rebuilt the insertIntoOData function to be as the following:

    insertServiceRequestIntoOData: function(evt) {

        var that = this;
        var token = null;
        var serviceUrl = "URL";

        var name_var = this.byId("tSubjectInput").getValue();
        var description_var = this.byId("tDescriptionArea").getValue();

        var oEntry = {};
        /*
         * oEntry 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) {
                token = xhr.getResponseHeader("X-CSRF-Token");

                // begin of odata send
                that.oModel.create("/MyCollection", oEntry, 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();
                });

            }
        });
    }