Reputation: 8297
I set the view.setModel(model)
, get the model for the view, and request for model.read("/entitySet('10000')")
.
The model is then filled up with /entitySet('10000')/properties
.
But it is difficult to assign them to view fields, as now in the view, <Text text="{property}">
doesn't work. It has to be <Text text="{/entitySet('10000')/property}">
.
On the other hand, if I set view's context binding to "/entitySet('10000')"
, then <Text text="{property}">
would start working.
Which one is the preferred method? When to use .read
?
Upvotes: 2
Views: 1282
Reputation: 18044
It's always important to be more expressive. Use the API that is specifically designed to do that one task.
Comparing the two variants:
myModel.read(sPath)
with text="{/path/property}"
myControl.bindElement(sPath)
with text="{property}"
I'd be perplexed about the 1st call whereas in the 2nd call, I'd know exactly what you want to achieve (You want to bind element. Alternatively, bindObject
can be also used).
The same applies to the framework. Since you're telling exactly what you want to achieve, the framework can improve its behavior based on your intent. E.g.: in (route)PatternMatched
handler when the user navigates to the same page, .bindElement
with the same path won't trigger another request since the model already stored the entity from the previous call. It can show the result immediately.
With .read
, however, the framework doesn't know what you want to achieve, so it sends the request right away regardless of the application state.
Additionally, the 1st variant is anything but future-proof. It relies on the cached results. It's almost a side-effect that it works at all. The problem is that there is no guarantee that this behavior will continue to work in later versions. Also there won't be read
method in V4 ODataModel.
v2.ODataModel#read
context
from the response. Repeating .read("<same path>")
always sends a new request.bindElement or bindObject
context
from the response and stores it internally so that the same request can return the data immediately.v4.ODataModel
does not support manual read. Imagine you've built your applications with the v2ODataModel.read
-jsonModel.setData
approach, and you need to migrate to v4
. Have fun. :)I honestly think that v2.ODataModel#read
should have never become a public method. I wouldn't encourage anyone to use .read
except of when reading the $count
value manually.
If the entity values need to be formatted, there are formatters and binding types out of the box which are also easy to extend.
If the application needs to restructure the response body, usually it's a sign of a poor design of the data model or the service not conforming to the OData spec.
Upvotes: 3
Reputation: 7250
I almost never use .read
if I want to use the results from an OData call directly in a binding context. The only time I use .read
is if I want to manipulate the results before doing anything with them.
Look at this example from the sdk for instance: https://ui5.sap.com/#/entity/sap.ui.table.Table/sample/sap.ui.table.sample.OData
Syntax on this kind of binding is similar to read but with a few differences in events, and a few different types of methods depending on what you want to bind. Binding to a view for instance uses bindElement
:
this.getView().bindElement("/entitySet('1000')");
After this, fields on that particular entity can be accessed as <Text text="{property}" />
.
Here's an example from one of my current apps with events and some other call parameters:
this.getView().bindElement({
path: `/Orders('${currentOrderNumber}')`,
parameters: {
expand: 'Texts'
},
events: {
dataRequested: _ => this.getView().setBusy(true),
dataReceived: data => {
if (!this.getView().getBindingContext()) {
// navigate to `Not Found` view
}
},
change: _ => this.getView().setBusy(false)
}
});
For a table, it's slightly different, since it depends on the aggregation you wish to bind, such as
oTable.bindRows({
path: "properties"
});
Which is the same as:
<Table rows="{properties}" />
Upvotes: 3
Reputation: 87
I almost agree with Jorg, but not entirely:
It really depends on what are you trying to achieve. If looking to display data from backend then the easiest way to go is with this.getView().bindElement()
but if you are in need to manipulate data before displaying (like formatting text, displaying images from base64 strings, etc) OR if you would like to create new entity using some of existing data, OR update the existing data - the this.getModel(sName).read()
is the way to go - as you can set read entity with all its deep entities to JSONModel in successCallback and manipulate it from the localModel.
If using localModel the dataBinding is pretty much the same in the view - except you have to additionally give model name to take data from. So for example, if in successCallback of your Model.read() you set your data to Model named "localModel":
this.getModel().read(sObjectPath, {
urlParameters: {
$expand: ""
},
success: function (oData) {
// "localModel" is name you gave in onInit function to your new JSONMOdel, when setting it to View e.g. this.getView().setModel(oJSONMOdel, "localModel")
this.getModel("localModel").setData(oData);
}
})
then in XML view you would indicate that
<Text text="{localModel>/mainPropertyName}"/>
// for displaying deep entities as List items or in Table
<List items="{localModel>/deepEntityName}">
<StandardListItem title="{localModel>propertyNamefromDeepEntity}" />
</List>
From my experience working with more complex apps that Read-Only - I always use Model.read().
Upvotes: -1