In an XML view, I present a sap.m.Table
with entries from an output ODataModel. Now the first 8 entries should be output for about 5 seconds and the remaining entries automatically reload, and switch in 5 second intervals, like a dashboard.
Here is an example: I have 30
entries.
- At the beginning → Show entries
1
to 8
.
- After 5 seconds → Show entries
9
to 16
.
- After next 5 seconds → Show
17
to 24
.
- After next 5 seconds → Show
25
to 30
.
- Then repeat from the beginning.
Would you have any idea how I can do that? Could it possibly realized on the routing function with transfer of the required parameters to the URL?
I have made a Plunker to demonstrate how this can be achieved: Plunker Demo.
In a nutshell, you can leverage the startIndex
and length
parameters of the ManagedObject#bindAggregation method. More specifically, you use them to bind the table repeatedly.
this.byId("list").bindItems({
path: "/Meetups",
template: this.byId("template"),
templateShareable: true,
startIndex: start,
length: SLICE_SIZE
});
Because you continually rebinding the table, you can simply create the template object inside the XML view as a dependent
, then you can access it via this.byId(...)
. We need to use the templateShareable
flag to indicate that the template will be reused in further bindings (on the next tick).
<dependents>
<StandardListItem id="template" title="{Title}"
description="{Description}" counter="{MeetupID}" />
</dependents>
Regarding the routing, I made two routes: one initial ("default") route and one route which specifies the start index ("withStart"). Both of them pointing of course to the same view.
"routes": [{
"pattern": "",
"name": "default",
"target": "main"
}, {
"pattern": "/{start}",
"name": "withStart",
"target": "main"
}]
The transition between "slices" is done with the help of jQuery.sap.delayedCall. You can also use a IntervalTrigger instead, but it might cause some problems if the view is not the first one shown (as the first "slice" might not be shown for the full 5 seconds, depending of course on how you implement it).
jQuery.sap.delayedCall(INTERVAL, this, this.onTick, [start]);
Then a tick happens (i.e. when we need to change the "slice"), we simply do a navigation to the withStart
route and increment the start
index parameter. At this point, we can also check if we need to start from zero again (if the start index is greater than the total count).
start += SLICE_SIZE;
if (this.count && start >= this.count) {
start = 0;
}
this.getOwnerComponent().getRouter().navTo("withStart", {start: start});
In order to find out the total count (to be able to determine if you should go to zero), you can use the information from the List / Table's ListBinding.
var oBinding = this.byId("list").getBinding("items");
if (oBinding.isLengthFinal()) {
this.count = oBinding.getLength();
}
One problem that you might face in a multi-view application is that, if the user navigates between your "dashboard" view and some other view, the delayedCall
might cause you to navigate back again to the "dashboard" view (i.e. the user might get "trapped" in the dashboard). To circumvent this, you could check to see if the view is visible first, before doing the navTo
call.
Later edit:
For improving performance due to loading times you can use two different approaches:
- Use the operation mode parameter when you are doing the binding. Setting it to
Client
will load all entries at once on the client side and the pagination mechanism will be done without further requests (at least in theory).
this.byId("list").bindItems({
path: "/Meetups",
template: this.byId("template"),
templateShareable: true,
startIndex: start,
length: SLICE_SIZE,
operationMode: OperationMode.Client
});
- Do an initial load of the data using the ODataModel.read method, store the results into a JSON Model and then use the JSON Model for binding the list instead of the OData Model.
var oModel = this.getView().getModel("myJsonModel");
this.getView().getModel().read("/Meetups", {
success: function(oData) {
oModel.setData(oData);
}
});