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);
}
},
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With