[ACCEPTED]-How to Bind OData $count from expanded collection in an XML view-sapui5
I had a similar issue. Although I am not 6 thrilled with my solution, it uses expression 5 binding and works without the need for a 4 separate formatter:
<List items="{/Categories}"} >
<ObjectListItem
title="{CategoryName}"
number="{= ${Products}.length }"
numberUnit="Products" />
</List>
Like @Jasper_07, you 3 still need to include Products
in the expand, but 2 you are ignoring most of the data coming 1 back.
I dont think its currently possible - $count 13 is an OData query option, the equivalent 12 in ODataListBinding is length, eg Products.length 11 I cant think of a way to bind to it
you 10 can achieve the count in a couple of ways 9 using a formatter
option 1 - the simplest, create 8 a list binding which reads the total number 7 of products, it does a synchronous call 6 and returns only the $count
function productCount(oValue) {
//return the number of products linked to Category // sync call only to get $count
if (oValue) {
var sPath = this.getBindingContext().getPath() + '/Products';
var oBindings = this.getModel().bindList(sPath);
return oBindings.getLength();
}
};
<List items="{/Categories}"} >
<ObjectListItem
title="{CategoryName}"
number="{path : 'CategoryName',formatter:'productCount'}"
numberUnit="Products"
</ObjectListItem>
</List>
option 2 - use 5 an expand and return a very small set of 4 data, in this case only CategoryName and 3 ProductID, the caveat here is whether you 2 have to by pass table paging to get full 1 list
function productCount(oValue) {
//read the number of products returned
if (oValue) {
return oValue.length;
}
};
<List items="{/Categories,parameters:{expand:'Products', select:'CategoryName,Products/ProductID'}}">
<ObjectListItem
title="{CategoryName}"
number="{path : 'Products',formatter:'productCount'}"
numberUnit="Products"
</ObjectListItem>
</List>
Well.. I had exactly the same requirement and didn't 4 want to perform the clever solution from 3 @jasper as it will load all Products collection 2 from the oData service.
This was the way 1 I solve it:
View
- Use a controller
- Give your list an ID
- Use a function on list's
updateFinished
event.
<mvc:View
controllerName="view.Root"
xmlns:mvc="sap.ui.core.mvc"
xmlns="sap.m"
>
<List id="list"
headerText="Categories"
items="{/Categories}"
growing="true"
growingThreshold="4"
growingScrollToLoad="true"
updateFinished=".countProducts"
>
<ObjectListItem
title="{description}"
numberUnit="Products"
/>
</List>
</mvc:View>
Controller
- Implement
countProducts
function - Use jQuery to request the $count for each list item - Notice how the URL is generated concatenating model's service URL with the item's binding context
- As jQuery uses asynchronous requests, by the time you get the first response, your
for
will be finished. So it can use IIFE to avoid filling just the last list item with your AJAX response
countProducts: function(e){
var m = sap.ui.getCore().getModel();
var items = this.byId("list").getItems();
for (var item_index = 0; item_index < items.length; item_index++) {
var item = items[item_index];
(function(_item) {
$.get(
m.sServiceUrl + _item.getBindingContextPath() + "/Categorias/$count",
function(count) {
_item.setNumber(count);
}
);
})(item);
}
}
I´d another solution using Manifest.json, Component.js 11 and Controller.js for similar Issue.
First, I 10 defined the Id in App.view.xml, for example:
<Title id="titleId" text="" level="H2"/>
After, I 9 check Manifest.json, in especial:
{
"sap.app": {
"dataSources": {
"AXXX": {
"uri": "https://cors-anywhere.herokuapp.com/https://services.odata.org/Northwind/Northwind.svc/",
Next, in 8 Componente.js at init:function() I put:
var oDataServiceUrl = this.getMetadata().getManifestEntry("sap.app").dataSources["AXXX"].uri;
console.log("oDataServiceUrl = ", oDataServiceUrl);
localStorage.setItem('oDataServiceUrl', oDataServiceUrl);
This 7 code read Manifest.json and get Url to oDataService 6 called AXXX.
Finnaly, I created one function 5 in App Controller, such as:
countCustomersInAXXX : function (oEvent) {
var suffix = 'Customers/$count';
var oDataServiceUrl = localStorage.getItem('oDataServiceUrl');
var oDataServiceUri = oDataServiceUrl.concat(suffix);
console.log('App.controller.js: oDataServiceUri', oDataServiceUri);
var count = $.ajax({type: "GET", url: oDataServiceUri, async: false}).responseText;
console.log('App.controller.js: countCustomersInAXXX:' , count);
this.getView().byId("titleId").setText(count);
}
This code get 4 the quantity of Customers and set the value 3 in titleId.
To start this process you can 2 user a button or one event, in my case I 1 use this Table property:
updateFinished="countCustomersInAXXX"
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.