I'm creating a little demo page that displays some straight forward functionality of UI5. This page consists of two main pages:
Carrid
).The table looks like this:
<Table id="detailTable" inset="false" class="sapUiResponsiveMargin">
<columns>
<Column>
<Text text="ID" />
</Column>
<Column>
<Text text="Flightnumber" />
</Column>
<Column>
<Text text="Starts in" />
</Column>
<Column>
<Text text="Departs at" />
</Column>
<Column>
<Text text="Lands in" />
</Column>
<Column>
<Text text="Lands at" />
</Column>
</columns>
</Table>
The data is bound to the columns with this code:
// Get routing data and show only entrys with the matched primary key (Carrid)
_onRouteMatched: function(oEvent) {
// ...
var oArgs = oEvent.getParameter("arguments");
var oFlightTable = oView.byId("detailTable");
oFlightTable.bindAggregation("items", {
path: "/CarrierSet(" + "'" + oArgs.flightPath + "'" + ")/FlightSet",
template: new sap.m.ColumnListItem({
cells: [
new sap.m.Text({
text: "{Carrid}"
}),
new sap.m.Text({
text: "{Connid}"
}),
new sap.m.Text({
text: "{Cityfrom}"
}),
new sap.m.Text({
text: "{Deptime}"
}),
new sap.m.Text({
text: "{Cityto}"
}),
new sap.m.Text({
text: "{Arrtime}"
})
]
})
});
}
The code works fine if the data can be shown without manipulating it first. But the fields {Deptime}
and {Arrtime}
have the type Edm.Time which I need to convert first in order to display it in a human readable form.
I was able to achieve this with this bit of code (I know, not the most efficient way, but im still learning. So if you have any improvements, feel free to post them):
pageTable.addEventDelegate({
onAfterRendering: function() {
var mTable = this.getView("FilterBarSimple").byId("detailTable");
var mModel = mTable.getModel();
var aItems = mTable.getItems();
// ----- TIME CONVERSION ----
var arrayTime = [];
for (var iTime = 0; iTime < aItems.length; iTime++) {
var iAdded = mModel.getProperty("Deptime", aItems[iTime].getBindingContext());
arrayTime.push(iAdded);
}
var timeFormat = sap.ui.core.format.DateFormat.getTimeInstance({
pattern: "kk:mm:ss"
});
var tz = new Date(0).getTimezoneOffset() * 60 * 1000;
var arrayTimeClean = [];
$.each(arrayTime, function(ii, ee) {
var timeStr = timeFormat.format(new Date(ee.ms + tz));
arrayTimeClean.push(timeStr);
});
}
});
This generates this output which is correct:
But I'm not able to correctly bind this manipulated data into the table again. I've tried it with the OData.read()
function and some other rather hacky approaches but I was never successful and I'm stuck with this problem for quite some time now.
If anyone has an idea or a suggestion, I'd be more than thankful if you let me know.
There is no need for "hacky approaches" or custom formatters in case you simply want to display the time, date, or timestamp in a human readable form. When defining property bindings, you can leverage the UI5 concept called Data Types (type
)doc which:
formatOptions
and constraints
.formatter
(See also Assigning binding modes).The type
for Edm.Time
should be an instance of sap/ui/model/odata/type/Time
.API Take a look at this (IMO must-read) documentation "Dates, Times, Timestamps, and Time Zones".
<Table xmlns="sap.m"
xmlns:core="sap.ui.core"
core:require="{
TypeForODataV2DateOnly: 'sap/ui/model/odata/type/DateTime',
TypeForODataV2Time: 'sap/ui/model/odata/type/Time',
TypeForODataTimestamp: 'sap/ui/model/odata/type/DateTimeOffset'
}"
items="{/MyEntitySet}"
><!-- ... -->
<ColumnListItem>
<!-- For OData V2 entity properties with Type="Edm.DateTime" and sap:display-format="Date" -->
<Text text="{
path: 'MyTimeZoneIndependentDate',
type: 'TypeForODataV2DateOnly',
constraints: {
displayFormat: 'Date'
}
}" />
<!-- For OData V2 entity properties with Type="Edm.Time" -->
<Text text="{
path: 'MyTimeZoneIndependentTime',
type: 'TypeForODataV2Time',
formatOptions: { style: 'long' }
}" />
<!-- For OData entity properties with Type="Edm.DateTimeOffset" -->
<DateTimePicker value="{
path: 'MyTimestamp',
type: 'TypeForODataTimestamp'
}" />
<!-- Applies also to other controls such as DatePicker, TimePicker, etc. -->
</ColumnListItem>
</Table>
Demo: https://embed.plnkr.co/F3t6gI8TPUZwCOnA
Note: about the core:require
-syntax, see "Require Modules in XML View and Fragment" which is supported as of UI5 1.69. For lower versions, use type: 'sap.ui.model.odata.type.<...>'
.
Review the 1st table from the topic "Dates, Times, Timestamps, and Time Zones", double-check with the table if the relevant EDM types in your $metadata
response are all correctly set accordingly, and use the corresponding sap/ui/model/odata/type/<...>
in the property binding:
<ThatControl xmlns="..."
xmlns:core="sap.ui.core"
core:require="{ ThatType: 'sap/ui/model/odata/type/<...>' }"
value="{
path: 'myODataModel>MyEntityProperty',
type: 'ThatType', (Optional in OData V4.* Required in V2.)
formatOptions: {...}, (Optional)
constraints: {
displayFormat: 'Date' (Required in V2 if Type = Edm.DateTime with sap:display-format = Date)
}
}"
>
* In V4, the OData property binding automatically determines the type
for you, unless it has targetType: 'any'
.
More related OData V2 and V4 samples: https://sdk.openui5.org/entity/sap.ui.model.odata.type