Reputation: 20852
Is there a way to access an internal counter or index property of list items in an XML view, while iterating over the items of a SAPUI5 List control? The use case could be to simply enumerate the items. Or in my case it would be to give a special treatment to the very first list item.
What I am looking for is something like the hypothetical $counter
in the following example:
<List items="{MyModel>/MyRootElement}">
<items>
<CustomListItem>
<Text text="This is element number {MyModel>$counter}." />
</CustomListItem>
</items>
</List>
I know I can solve this using JS in the controller. But I would be interested in a pure XML solution.
Upvotes: 1
Views: 3708
Reputation: 5206
Based on my knowledge, there is no built-in "pseudo-property" that would contain the index of the element. If we especially think about sorting, then I would imagine that there would be developers wanting the numbering to reflect the sorting and other developers wanting it to be stable with regards to sorting.
Nevertheless, in some concrete cases, it is possible to actually number your rows using a pure XML solution.
If the MyRootElement
is an array, you could always do something like (working fiddle):
<List items="{/MyRootElement}">
<StandardListItem title="{name}"
counter="{= ${/MyRootElement}.indexOf(${}) + 1 }" />
</List>
If it is an object (i.e. a map-like structure) then you will need to use the Object.values() function. It provides the correct numbering because it is guaranteed to give the values in the same order as a for .. in loop which is actually used by the Model to create the bindings and ultimately the list items. It should be noted that the Object.values()
function is not supported in IE and might require a polyfill. Example (and working fiddle):
<List items="{/MyRootElement}">
<StandardListItem title="{name}"
counter="{= Object.values(${/MyRootElement}).indexOf(${}) + 1 }" />
</List>
In the code samples, I have used the ${}
construct to access the current, unnamed model's binding context's data object.
The rules related to building the binding paths are the following (as specified in the documentation):
>
sign. If this part is skipped, then the unnamed (default) model is used. The rest of the path after the >
sign is used to find the referenced data inside the model./
, then it is an absolute path (the referenced data lookup is performed from the root object of the model). Otherwise, it is a relative path./
sign and then the JSON object tree is traversed using the attribute names obtained from this split.Concretely, in the case of ${}
, the binding path itself is '' (an empty string). Using the rules above, this would be a relative path for the unnamed (default) model. As the path is empty, no attribute traversal is done (because there are no path components obtained after the path split).
Similarly, for named models, the ${MyModelName>}
expression binding would have the same effect.
Upvotes: 5
Reputation: 2265
I don't know about any counter in the table, however a workaround could be using a factory function and getting the row number fromt he row id:
Here the DEMO using Northwind and here the snippet:
<html>
<head>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<meta charset="utf-8">
<title>MVC with XmlView</title>
<!-- Load UI5, select "blue crystal" theme and the "sap.m" control library -->
<script id='sap-ui-bootstrap'
src='https://sapui5.hana.ondemand.com/resources/sap-ui-core.js'
data-sap-ui-theme='sap_bluecrystal'
data-sap-ui-libs='sap.m'
data-sap-ui-xx-bindingSyntax='complex'></script>
<!-- DEFINE RE-USE COMPONENTS - NORMALLY DONE IN SEPARATE FILES -->
<!-- define a new (simple) View type as an XmlView
- using data binding for the Button text
- binding a controller method to the Button's "press" event
- also mixing in some plain HTML
note: typically this would be a standalone file -->
<script id="view1" type="sapui5/xmlview">
<mvc:View xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc" controllerName="my.own.controller">
<Page>
<Table items="{path:'/Orders', factory: '.createRow'}">
<columns>
<Column>
<Text text="#"/>
</Column>
<Column>
<Text text="Order ID"/>
</Column>
</columns>
</Table>
</Page>
</mvc:View>
</script>
<script>
// define a new (simple) Controller type
sap.ui.controller("my.own.controller", {
createRow: function (sId, oContext) {
console.log(sId);
console.log(oContext);
var rowNumber = sId.split("-")[sId.split("-").length-1];
var oRow = new sap.m.ColumnListItem({
cells: [
new sap.m.Text({
text: rowNumber
}),
new sap.m.Text({
text: {path: "OrderID"}
})
]
})
return oRow;
}
});
/*** THIS IS THE "APPLICATION" CODE ***/
// create a Model and assign it to the View
// Using here the HEROKU Proxy to avoid a CORS issue
var uri = "https://cors-anywhere.herokuapp.com/services.odata.org/Northwind/Northwind.svc"; // local proxy for cross-domain access
var oNorthwindModel = new sap.ui.model.odata.ODataModel(uri, {
maxDataServiceVersion: "2.0"
});
// instantiate the View
var myView = sap.ui.xmlview({viewContent:jQuery('#view1').html()}); // accessing the HTML inside the script tag above
// Set the OData Model
myView.setModel(oNorthwindModel);
myView.placeAt('content');
</script>
</head>
<body id='content' class='sapUiBody'>
</body>
</html>
Upvotes: 0