2
votes

I've tried to prepare data from an OData source to show it in a bar graph in my fiori app. For this, I setup the OData model in the manifest.json. A test with a list, simply using

items="{path : 'modelname>/dataset'}

works fine and shows the content.

To prepare data for a diagram (VizFrame), I used the onInit() function in the controller of the view (mvc:XMLView). The data preparation is similar to the one discussed in question.

At first I obtain the ODataModel:

var oODataModel = this.getOwnerComponent().getModel("modelname");

Next I do the binding:

var oBindings = oODataModel.bindList("/dataset");

Unfortunately, the oBindings().getContexts() array is always empty, and also oBindings.getLength() is zero. As a consequence, the VizFrame shows only "No Data".

May it be that the data model is not fully loaded during the onInit() function, or do I misunderstand the way to access data?

Thanks in advance

Update I temporary solved the problem by using the automatically created bind from the view displaying the data as list. I grep the "dataReceived" event from the binding getView().byId("myList").getBindings("items") and do my calculation there. The model for the diagram (since it is used in a different view) is created in the Component.js, and registered in the Core sap.ui.getCore().setModel("graphModel"). I think this solution is dirty, because the graph data depends on the list data from a different view, which causes problems, e.g. when you use a growing list (because the data in the binding gets updated and a different range is selected from the odata model). Any suggestions, how I can get the odata model entries without depending on a different list?

4

4 Answers

2
votes

The following image outlines the lifecycle of your UI5 application.

enter image description here

Important are the steps which are highlighted with a red circle. Basically, in your onInit you don't have full access to your model via this.getView().getModel().

That's probably why you tried using this.getOwnerComponent().getModel(). This gives you access to the model, but it's not bound to the view yet so you don't get any contexts.

Similarly metadataLoaded() returns a Promise that is fullfilled a little too early: Right after the metadata has been loaded, which might be before any view binding has been done.

What I usually do is

  • use onBeforeRendering

This is the lifecycle hook that gets called right after onInit. The view and its models exist, but they are not yet shown to the user. Good possibility to do stuff with your model.

  • use onRouteMatched

This is not really a lifecycle hook but an event handler which can be bound to the router object of your app. Since you define the event handler in your onInit it will be called later (but not too late) and you can then do your desired stuff. This obviously works only if you've set up routing.

1
votes

You'll have to wait until the models metadata has been loaded. Try this:

onInit: function() {
    var oBindings;
    var oODataModel = this.getComponent().getModel("modelname");
    oODataModel.metadataLoaded().then(function() {
        oBindings = oODataModel.bindList("/dataset");
    }.bind(this));
},
0
votes

May it be that the data model is not fully loaded during the onInit() function, or do I misunderstand the way to access data?

You could test if your model is fully loaded by console log it before you do the list binding

console.log(oODataModel);
var oBindings = oODataModel.bindList("/dataset");

If your model contains no data, then that's the problem.

0
votes

My basic misunderstanding was to force the use of the bindings. This seems to work only with UI elements, which organize the data handling. I switched to

oODataModel.read("/dataset", {success: function(oEvent) {
    // do all my calculations on the oEvent.results array
    // write result into graphModel
    }
});

This whole calculation is in a function attached to the requestSent event of the graphModel, which is set as model for the VizFrame in the onBeforeRendering part of the view/controller.