I want to display a chart (sap.viz.ui5.controls.VizFrame
) that visualizes data from an OData Service. However, the data of the service has to be manipulated. See the example below:
Main.view.xml
<mvc:View controllerName="demo.chart.controller.Main" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m">
<Shell id="shell">
<App id="app">
<pages>
<Page id="page" title="Chart Demo">
<content></content>
</Page>
</pages>
</App>
</Shell>
</mvc:View>
Chart.fragment.xml
<c:FragmentDefinition xmlns:c="sap.ui.core" xmlns:viz="sap.viz.ui5.controls" xmlns:viz.data="sap.viz.ui5.data"
xmlns:viz.feeds="sap.viz.ui5.controls.common.feeds">
<viz:VizFrame uiConfig="{applicationSet:'fiori'}" vizType='donut'>
<viz:dataset>
<viz.data:FlattenedDataset data="{manipulatedData>/}">
<viz.data:dimensions>
<viz.data:DimensionDefinition name="Gender" value="{manipulatedData>gender}"/>
</viz.data:dimensions>
<viz.data:measures>
<viz.data:MeasureDefinition name="Amount" value="{manipulatedData>amount}"/>
</viz.data:measures>
</viz.data:FlattenedDataset>
</viz:dataset>
<viz:feeds>
<viz.feeds:FeedItem uid="color" type="Dimension" values="Gender"/>
<viz.feeds:FeedItem uid="size" type="Measure" values="Amount"/>
</viz:feeds>
</viz:VizFrame>
</c:FragmentDefinition>
Main.controller.js
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/model/json/JSONModel",
"sap/ui/core/Fragment"
], function (Controller, JSONModel, Fragment) {
"use strict";
return Controller.extend("demo.chart.controller.Main", {
onInit: function () {
const mDefault = this.getOwnerComponent().getModel();
const mManipulatedData = new JSONModel([{
gender: "F",
amount: 0
}, {
gender: "M",
amount: 0
}, {
gender: "X",
amount: 12
}]);
this.getView().setModel(mManipulatedData, "manipulatedData");
console.log(this.getView().getModel("manipulatedData"));
mDefault.read("/ContactSet", {
success: oData => {
const aManipulatedData = mManipulatedData.getData();
oData.results.forEach(entry => {
aManipulatedData.forEach(type => {
if (entry.Sex === type.gender) {
type.amount++
}
})
});
Fragment.load({
name: "demo.chart.view.Chart",
controller: this
}).then(oFragment => {
this.getView().addDependent(oFragment);
this.byId("page").addContent(oFragment);
});
}
})
}
});
});
Structure of the service (GWSAMPLE_BASIC/ContactSet
)
{
"d": {
"results": [
{
"__metadata": {
"id": "https://sapes5.sapdevcenter.com/sap/opu/odata/IWBEP/GWSAMPLE_BASIC/ContactSet(guid'0050568c-901d-1eda-bcae-e8394de7e116')",
"uri": "https://sapes5.sapdevcenter.com/sap/opu/odata/IWBEP/GWSAMPLE_BASIC/ContactSet(guid'0050568c-901d-1eda-bcae-e8394de7e116')",
"type": "GWSAMPLE_BASIC.Contact"
},
"Address": {
"__metadata": {
"type": "GWSAMPLE_BASIC.CT_Address"
},
"City": "Walldorf",
"PostalCode": "69190",
"Street": "Robert-Koch-Straße",
"Building": "1",
"Country": "DE",
"AddressType": "02"
},
"ContactGuid": "0050568c-901d-1eda-bcae-e8394de7e116",
"BusinessPartnerID": "0100000000",
"Title": "",
"FirstName": "Karl",
"MiddleName": "",
"LastName": "Müller",
"Nickname": "",
"Initials": "",
"Sex": "M",
"PhoneNumber": "0622734567",
"FaxNumber": "0622734004",
"EmailAddress": "do.not.reply@sap.com",
"Language": "EN",
"DateOfBirth": null,
"ToBusinessPartner": {
"__deferred": {
"uri": "https://sapes5.sapdevcenter.com/sap/opu/odata/IWBEP/GWSAMPLE_BASIC/ContactSet(guid'0050568c-901d-1eda-bcae-e8394de7e116')/ToBusinessPartner"
}
}
}
]
}
}
So, as you can see, I'm only interested in the aggregated values of the Sex
property. My current solution is to loop through all the entries of the entity set and increase the property in a custom JSON model. This is not only very inperformant because you do the heavy-lifting on the client side, it also requires you to know all the possible values for the data displayed in the chart right away. Is there a way to do this with OData queries or do I have to create a new entity set with the comulated data in my SAP system?