1

I just ran into a problem where I am not sure how to solve.

Background: I've got an App with two views:

  • 1st one to input a number,
  • 2nd one to see the details.

After the view switched to the detail view, I would call the bindElement() to get my data from the backend.

_onRoutePatternMatched: function(oEvent) {
  // ...
  this.getView().bindElement({
    path: "/EntitySet('" + id+ "')"
  });
},

Problem is that the ID is quite often the same, hence, the method will call the backend only if the ID is different from the last call.

So I tried to solve the problem by using the following:

this.getView().getModel().read("/EntitySet('" + id+ "')",{
  success: function(oData, response) {
    that.getView().setModel(oData, "");
  }
});

By this, the data is always up to date. But now the binding is a bit different.

Binding with bindElement():

{
  "id": "1234",
  "propety1": "abc",
  // ...
}

Binding with setModel() and id = 1234:

{
  "EntitySet('1234')": {
    "id": "1234",
    "propety1": "abc",
    // ...
  }
}

For the first way, my binding looked like this:

<ObjectHeader title="{id}">

Now, it would have to look like this:

<ObjectHeader title="{/EntitySet('1234')/id}">

And here I have a problem, because the value of id (in this case 1234) will always be different and so the binding won't work. I can't bind directly to the ObjectHeader, because I will need some properties from the model later. That is the reason I am binding to the view so that all that remain available.

My idea was to edit the binding inside the success method of the read method. I would like to delete the surrounding element. Do you have an idea, how to do this? Or even a simpler/better idea to solve my pity?

Edit: I forgot to mention the refresh method. This would be possible, but where do I have to put it? I don't want to call the backend twice.

Boghyon Hoffmann
  • 17,103
  • 12
  • 72
  • 170
OverBurned
  • 45
  • 10

1 Answers1

4

Simply call the API myODataModel.invalidateEntry(<key>) before binding the context in order to retrieve the latest data.

// after $metadata loaded..
const model = this.getOwnerComponent().getModel("odata");
const key = model.createKey(/*...*/) //See https://stackoverflow.com/a/47016070/5846045
model.invalidateEntry(key); // <-- before binding
this.getView().bindElement({
  path: "odata>/" + key,
  // ...
});

From https://embed.plnkr.co/b0bXJK?show=controller/Detail.controller.js,preview


invalidateEntrydoc

Invalidate a single entry in the model data.

Mark the selected entry in the model cache as invalid. Next time a context binding or list binding is done, the entry will be detected as invalid and will be refreshed from the server.

Community
  • 1
  • 1
Boghyon Hoffmann
  • 17,103
  • 12
  • 72
  • 170
  • it looks like that i haven't read the documentation at all... well at least i did not properly – OverBurned Dec 18 '19 at 20:14
  • 1
    You solution works absolutely fine and the sample is really awesome! It will take hours to understand everything in it but it will be worth it – OverBurned Dec 18 '19 at 20:16
  • Do you have some good tutorial/documentation for the parameters and how they work inside the `bindElement()` method? `@BoghyonHoffmann` – OverBurned Dec 18 '19 at 20:57
  • 1
    @OverBurned The options for the `bindElement` is dependent on the model implementation. For OData, for example, see https://ui5.sap.com/#/api/sap.ui.model.odata.v2.ODataContextBinding – Boghyon Hoffmann Dec 19 '19 at 01:16
  • You are awesome! Thanks a lot! I will give all of this a try in my sandbox – OverBurned Dec 19 '19 at 05:40