Search code examples
odatasapui5sap-fiori

How to refresh previously bound entity every time user visits the page


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.


Solution

  • 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.