9
votes

My goal is to write a SAPUI5 Fiori app with routing support. One mail goal is to have passable URLs. For example in an E-Mail like "please approve this: link". The link is an URL matched by my rounting config, e.g.index.html#/applicants/8.

I use a typical sap.m.SplitApp kind of application. Clicking a list item in masterview changes the URL to index.html#/applicants/[id of entry in JSON]. I can click on the list, my defined routes are getting matched and the apps loads the (applicant) data as expected.

However, and here comes my question, this doeas not work when using an URL directly, say pasting [my url]/index.html#/applicants/8 into my browser. The app is launched but no detail data is loaded. I have to click on another list item again to get the data.

Actually, the controller is called when passing the URL, but it seems the model is not initiated and undefined. My JSON model is bound in the createContent function of my Component.js

// Update 2015-05-14 The problems seems to be around the getData() function. I have the model, it has the entries, but getData() returns undefined for the first time my app is loaded. I recently read getData() is deprecated. How should I improve my coding below?

// Component.js
ui5testing.Component.prototype.createContent = function(){
  // create root view
  var oView = sap.ui.view({
    id : "app",
    viewName : "ui5testing.view.Main",
    type : "JS",
    viewData : {
        component : this
    }
  var oModel = new sap.ui.model.json.JSONModel("model/mock_applicants.json");
  oView.setModel(oModel);
  [...]
  return oView;
});
// Master controller
handleApplicantSelect : function (evt) {
    var oHashChanger = sap.ui.core.routing.HashChanger.getInstance();
    var context  = evt.getParameter("listItem").getBindingContext();
    var path = context.getPath();
    var model = this.getView().getModel();
    var item =  model.getProperty(path);
    oHashChanger.setHash("applicants/" + item.id);
},

// Detail controller
onInit: function() {
    this.router = sap.ui.core.UIComponent.getRouterFor(this);
    this.router.attachRoutePatternMatched(this._handleRouteMatched, this);
},

_handleRouteMatched : function(evt){        
    var objectId = evt.getParameter("arguments").id;
    var model = this.getView().getModel();
    var data = model.getData()["applicants"];
    var pathId;

    if (data) {
        for (var i = 0; data.length; i++) {
            if ( objectId == data[i].id ) {
                pathId = i;
                break;
            }
        }

        var sPath = "/applicants/" + pathId;

        var context = new sap.ui.model.Context(model, sPath)
        this.getView().setBindingContext(context);              
    }
},
1
is createContent called? How and where do you set the model? this.getView().getModel(); doesn't sound like a good idea when the model is not already attached to the particular view BEFORE.cschuff
Sorry, I got it fixed already. See update.SDD64
Sorry again, after a refactor the issue emerged again. The model is set in the Compoent.js createContent(). Set to the Main root view.SDD64
Havent seen a code that says router.navTo. You are probably just trying to change the hash. Please consider using router. Else try and send me the code. I will be able to solve it.Naresh Kumar Devalapally
@NareshKumarDevalapally Thank you for your hint about using the router. The code above is outdated, I recently did what you recommended and switched to router.navToSDD64

1 Answers

4
votes

As you've figured out that getData() returns undefined for the first time, which means the model data is still not yet loaded. So you can make use of attachRequestCompleted method of the model & fire an event from the component & listen to that event in the detail controller to ensure the routerPatternMatched() gets executed only after the data is loaded.

//Component.js

var oModel = new sap.ui.model.json.JSONModel("model/mock_applicants.json");

oModel.attachRequestCompleted(jQuery.proxy(function(){
   this.fireEvent("MockDataLoaded"); // fireEvent through component
},this));

oView.setModel(oModel);

//Detail controller

onInit : function(){

this.router = sap.ui.core.UIComponent.getRouterFor(this);  

var oComponent = this.getOwnerComponent();

oComponent.attachEvent("MockDataLoaded",jQuery.proxy(function(){
   this.router.attachRoutePatternMatched(this._handleRouteMatched, this);
},this));

}

Or the simplest & but the dirty way would be to make an synchronous request instead of an async request to load data.

var oModel = new sap.ui.model.json.JSONModel();

oModel.loadData(""model/mock_applicants.json",{bAsync:false});

oView.setModel(oModel);