0
votes

I have an app which needs to check if the user has multiple accounts when it is first loaded. Most of them don't, so they should be taken straight into the main app view.
If they do have multiple accounts, they should be taken to a screen which allows them to select with which account they want to continue. The users with only one account should never see this selection page.

I have an OData call which returns the result of a backend check to see if the user has multiple accounts.

How can I dynamically set the rootView property of the component's metadata so it acts according to the behaviour defined above?

My research suggests if the rootView property is not set in the component metadata, the root view must be defined in the createContent() method.

My problem seems to stem around the asynchronous call to the OData, with createContent() executing before the OData result functions have set the variable to decide which view to see.

EDIT: I've changed the title to better reflect the likely cause of my problem. How can I keep the asynchronous calls but prevent createContent() from eventing before those calls are completed? Adding in something like the EventBus still doesn't work as it seems the application won't wait for it, and I just get an error about not being able to find the view.

My code below:

Declaration at the top of the file. By default view is the App since most users don't have multiple accounts. The multiple accounts is a rarer exception.

var sRootView = "view.App"; //default value of root view  
sap.ui.core.UIComponent.extend("MY_APP.Component", {

Component.js

init: function(){
...

this.oModel = new sap.ui.model.odata.ODataModel("/odatasvc");
that = this;
var aBatch = [];
aBatch.push(this.oModel.createBatchOperation("/multiple_account_check", "GET"));

makeCall = function(){
  var oDef = $.Deferred();
  utils.oDataCalls.read(that.oModel, aBatch, oDef);
  return oDef.promise();
};

var promise = makeCall();
var aResults = [];

promise.done(function(data) {
  for (var i=0; i<data.length; i++) {
    aResults.push(data);
  }
  that.checkAccounts(aResults[0]);
});

The createContent function.

createContent : function(){ 
    var oView = sap.ui.view({ 
      id : "meViewId",
      viewName : sRootView,
      type : "XML" });
    return oView;
  },

The function to check OData result for multiple accounts.

  checkAccounts : function(aResults){
    if(aResults.length == 1){ //one account
      that.oRouter.navTo("home");
    }
    else if(aResults.length > 1){ //multiple accounts
      sRootView = "view.multipleAccountsView"; //changed value used in createContent    
      that.oRouter.navTo("multipleAccounts");
    }
  }
1
Would anyone be able to tell me where the createContent function is called from? I want to try controlling when that function calls createContent.MKHC

1 Answers

-1
votes

You should be able to make the OData call synchronously by passing async as false to ODataModel method read. E.g:

oModel.read{"path", {async: false}};

If you implement this inside utils.oDataCalls.read, it might also require reworking the promise in that function.