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
.Follow 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>
Note: about the core:require
-syntax, see Require Modules in XML View and Fragment.
Plunker (OData V2): embed.plnkr.co/F3t6gI8TPUZwCOnA
Demo Kit - OData types (V2 and V4): sdk.openui5.org/entity/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, and use the corresponding sap/ui/model/odata/type/<...>
in your 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'
.