Download table to spreadsheet - uitableview

I have a sap.m.Table created. I need to download it to excel.
For that I have followed this sample. Yet the file, although exported, it only contains the titles of each column, rows seem to be kind of known by the file but cells are empty (check image below).
In my controller I have the following:
onExport : function () {
var oTable = this.getView().byId("lineItemsList"),
oRowBinding, aCols, oSettings, oSheet;
oRowBinding = oTable.getBinding("items");
aCols = this.createColumnConfig();
oSettings = {
workbook: {
columns: aCols
//hierarchyLevel: 'Level'
},
dataSource: oRowBinding,
fileName: "WBS Elements.xlsx"
//worker: false // We need to disable worker because we are using a MockServer as OData Service
};
oSheet = new Spreadsheet(oSettings);
oSheet.build().finally(function() {
oSheet.destroy();
});
},
Then the Column Config in controller:
createColumnConfig: function() {
var aCols = [];
aCols.push({
//label: 'Nivel',
property: "Level",
type: EdmType.String,
});
aCols.push({
label: "WBS Element",
property: "WBS Element",
type: EdmType.String,
});
aCols.push({
property: "Description",
type: EdmType.String
});
aCols.push({
property: "Basic Start",
type: EdmType.Date
});
aCols.push({
property: "Basic Finish",
type: EdmType.Date
});
aCols.push({
property: "Actual Start",
type: EdmType.Date,
});
aCols.push({
property: "Actual Finish",
type: EdmType.Date
});
aCols.push({
property: "Plan PoC%",
type: EdmType.Number
});
aCols.push({
property: "Act PoC%",
type: EdmType.Number
});
aCols.push({
property: "Plan Cost",
type: EdmType.Number
});
aCols.push({
property: "Actual Cost",
type: EdmType.Number
});
aCols.push({
property: "Budget",
type: EdmType.Number
});
aCols.push({
property: "Curr. Year Budget",
type: EdmType.Number
});
aCols.push({
property: "Status",
type: EdmType.String
});
aCols.push({
property: "Currency",
type: EdmType.String
});
return aCols;
}
And last, the table definition in XML View (took away toolbar definition and other stuff so to focus on relevant):
<semantic:content>
<Table
id="lineItemsList"
width="auto"
items="{
path: '/ItProjWbsSet',
sorter: {
path: 'Pspid',
descending: false
}
}"
mode="MultiSelect"
updateFinished=".onUpdateFinished"
selectionChange="onSelectionChange"
noDataText="{i18n>detailLineItemTableNoDataText}"
busyIndicatorDelay="{detailView>/delay}">
<columns>
<Column demandPopin="false" minScreenWidth="Phone">
<Text text="Level"/>
</Column>
<Column demandPopin="false" width="12em" minScreenWidth="Phone">
<Text text="WBS Element"/>
</Column>
<Column demandPopin="false" minScreenWidth="Tablet" visible="{= !${device>/system/phone}}">
<Text text="Basic Start"/>
</Column>
<Column demandPopin="false" minScreenWidth="Tablet" visible="{= !${device>/system/phone}}">
<Text text="Basic Finish"/>
</Column>
<Column demandPopin="false" minScreenWidth="Tablet" visible="{= !${device>/system/phone}}">
<Text text="Actual Start"/>
</Column>
<Column demandPopin="false" minScreenWidth="Tablet" visible="{= !${device>/system/phone}}">
<Text text="Actual Finish"/>
</Column>
<Column demandPopin="false" minScreenWidth="Phone" visible="{= !${device>/system/phone}}">
<Text text="Plan PoC%"/>
</Column>
<Column demandPopin="false" minScreenWidth="Phone" visible="{= !${device>/system/phone}}">
<Text text="Actual PoC%"/>
</Column>
<Column demandPopin="false" minScreenWidth="Tablet" visible="{= !${device>/system/phone}}">
<Text text="Plan Cost"/>
</Column>
<Column demandPopin="false" minScreenWidth="Tablet" visible="{= !${device>/system/phone}}">
<Text text="Act.Cost"/>
</Column>
<Column demandPopin="false" minScreenWidth="Tablet" visible="{= !${device>/system/phone}}">
<Text text="Budget"/>
</Column>
<Column demandPopin="false" minScreenWidth="Tablet" visible="{= !${device>/system/phone}}">
<Text text="Curr.Year Budget"/>
</Column>
<Column demandPopin="false" minScreenWidth="Tablet" visible="{= !${device>/system/phone}}">
<Text text="Status"/>
</Column>
</columns>
<items>
<ColumnListItem id="listLayout">
<cells>
<Text text="{Stufe}"/>
<ObjectIdentifier
title="{Pspid}"
text="{Post1}"/>
<Text text="{path : 'Pstrt',
type : 'sap.ui.model.type.Date',
formatOptions: { style : 'short'}}"/>
<Text text="{path : 'Pende',
type : 'sap.ui.model.type.Date',
formatOptions: { style : 'short'}}"/>
<Text text="{path : 'Istrt',
type : 'sap.ui.model.type.Date',
formatOptions: { style : 'short'}}"/>
<Text text="{path : 'Iende',
type : 'sap.ui.model.type.Date',
formatOptions: { style : 'short'}}"/>
<ObjectNumber
number="{
parts:[{path:'PlanCost'},{path:'CurrKey'}],
type: 'sap.ui.model.type.Currency',
formatOptions: {showMeasure: false}
}"
unit="{CurrKey}" />
<ObjectNumber
number="{
parts:[{path:'ActualCost'},{path:'CurrKey'}],
type: 'sap.ui.model.type.Currency',
formatOptions: {showMeasure: false}
}"
unit="{CurrKey}" />
<ObjectNumber
number="{
parts:[{path:'Budget'},{path:'CurrKey'}],
type: 'sap.ui.model.type.Currency',
formatOptions: {showMeasure: false}
}"
unit="{CurrKey}" />
<ObjectNumber
number="{
parts:[{path:'CurrYrBud'},{path:'CurrKey'}],
type: 'sap.ui.model.type.Currency',
formatOptions: {showMeasure: false}
}"
unit="{CurrKey}" />
<Text text="{Status}"/>
</cells>
</ColumnListItem>
</items>
</Table>
</semantic:content>

You need to use as property name the exact same string as it is called in your viewModel/oData service.
aCols.push({
label: "Actual Cost"
property: "ActualCost", // Needs to be property name
type: EdmType.Number
});
For the budget it already matched and therefore a '0' was shown in the excel.

Related

How can I make space between the navigation elements in Material Top Tab Navigation?

I have the below code:
const TopNavBar = () => {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={{}}
style={{paddingTop: StatusBar.currentHeight}}>
<Tab.Screen
options={{
title: ({color, focused}) => (
<Icon
size={25}
name={focused ? 'home' : 'home-outline'}
color={focused ? 'blue' : '#272727'}
/>
),
}}
component={Profile}
name="Home"
/>
<Tab.Screen
options={{
title: ({color, focused}) => (
<Icon
size={25}
name={focused ? 'person' : 'person-outline'}
color={focused ? 'blue' : '#272727'}
/>
),
}}
component={Profile}
name="Profile"
/>
</Tab.Navigator>
</NavigationContainer>
);
};
Which outputs:
But what I want is this:
Essentially only the profile button and the drawer only clickable
How can I achieve this?

UI5 TreeTable displays flat Hierarchy despite using Hierarchy-Annotations

I'm facing a problem with sap.ui.table.TreeTable.
My goal is to develop an SAP Fiori App that displays Tree Data which it receives via an OData V2 Service. For this project I am using the SAP Business Application Studio.
Here's the example I worked with and how I want my app to look like: https://sapui5.hana.ondemand.com/#/entity/sap.ui.table.TreeTable/sample/sap.ui.table.sample.TreeTable.BasicODataTreeBinding
This is what my App looks like right now...
As you can see the TreeTable is filled with the information it gets from my OData service. The problem I'm facing is that it just prints the elements without putting them into hierarchical order.
The "Einzelrollen" element is supposed to be a child of the "Rollen" element, as you can see when looking at the hierarchy-level / nodeid / parentNodeId.
The weird thing about this is, that the Tree-Annotation-Binding seemed to work, since the drillState element functions the way it should be --> the elements below the "Langtext"-element don't have an "expand" option, since they are Leafs.
So why does it not work with the hierarchical annotation elements?
Really hope somebody can help me out, looking forward to your guys suggestions! Thanks in advance!
Code below:
View.xml
<mvc:View
controllerName="treetable.controller.tableView"
xmlns:mvc="sap.ui.core.mvc"
displayBlock="true"
xmlns="sap.ui.table"
xmlns:m="sap.m">
<TreeTable
id="treeTable"
selectionMode="Single"
enableColumnReordering="false"
rows="{
path : '/NodeSet',
parameters : {
treeAnnotationProperties : {
hierarchyLevelFor : 'HierarchyLevel',
hierarchyNodeFor : 'NodeId',
hierarchyParentNodeFor : 'ParentNodeID',
hierarchyDrillStateFor : 'DrillState'
}
}
}">
<columns>
<Column label="Description">
<template>
<m:Text text="{Description}" wrapping="false" />
</template>
</Column>
<Column label="HierarchyLevel">
<template>
<m:Text text="{HierarchyLevel}" wrapping="false" />
</template>
</Column>
<Column label="NodeId">
<template>
<m:Text text="{NodeId}" wrapping="false" />
</template>
</Column>
<Column label="ParentNodeID">
<template>
<m:Text text="{ParentNodeID}" wrapping="false" />
</template>
</Column>
</columns>
</TreeTable> </mvc:View>
metadata.xml
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:sap="http://www.sap.com/Protocols/SAPData">
<edmx:DataServices m:DataServiceVersion="2.0">
<Schema Namespace="Z_ODATA_EXAMPLE_SRV" xml:lang="en" sap:schema-version="1" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
<EntityType Name="Node" sap:content-version="1">
<Key>
<PropertyRef Name="NodeId"/>
</Key>
<Property Name="NodeId" Type="Edm.Int32" Nullable="false" sap:unicode="false" sap:label="ID" sap:hierarchy-node-for="NodeId"/>
<Property Name="HierarchyLevel" Type="Edm.Int32" Nullable="false" sap:unicode="false" sap:hierarchy-level-for="NodeId"/>
<Property Name="ParentNodeID" Type="Edm.Int32" sap:unicode="false" sap:hierarchy-parent-node-for="NodeId"/>
<Property Name="DrillState" Type="Edm.String" Nullable="false" MaxLength="8" sap:unicode="false" sap:hierarchy-drill-state-for="NodeId"/>
<Property Name="Description" Type="Edm.String" Nullable="false" MaxLength="80" sap:unicode="false"/>
</EntityType>
<EntityContainer Name="Z_ODATA_EXAMPLE_SRV_Entities" m:IsDefaultEntityContainer="true" sap:supported-formats="atom json xlsx">
<EntitySet Name="NodeSet" EntityType="Z_ODATA_EXAMPLE_SRV.Node" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:pageable="false" sap:content-version="1"/>
</EntityContainer>
<atom:link rel="self" href="https://dae:1234/sap/opu/odata/sap/Z_ODATA_EXAMPLE_SRV/$metadata" xmlns:atom="http://www.w3.org/2005/Atom"/>
<atom:link rel="latest-version" href="https://dae:1234/sap/opu/odata/sap/Z_ODATA_EXAMPLE_SRV/$metadata" xmlns:atom="http://www.w3.org/2005/Atom"/>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
manifest.json
{
"_version": "1.32.0",
"sap.app": {
"id": "treetable",
"type": "application",
"i18n": "i18n/i18n.properties",
"applicationVersion": {
"version": "1.0.0"
},
"title": "{{appTitle}}",
"description": "{{appDescription}}",
"resources": "resources.json",
"ach": "ach",
"dataSources": {
"mainService": {
"uri": "/sap/opu/odata/sap/Z_ODATA_EXAMPLE_SRV",
"type": "OData",
"settings": {
"odataVersion": "2.0",
"localUri": "localService/metadata.xml"
}
}
}
},
"sap.ui": {
"technology": "UI5",
"icons": {
"icon": "sap-icon://task",
"favIcon": "",
"phone": "",
"phone#2": "",
"tablet": "",
"tablet#2": ""
},
"deviceTypes": {
"desktop": true,
"tablet": true,
"phone": true
}
},
"sap.ui5": {
"flexEnabled": false,
"rootView": {
"viewName": "treetable.view.tableView",
"type": "XML",
"async": true,
"id": "tableView"
},
"dependencies": {
"minUI5Version": "1.66.0",
"libs": {
"sap.ui.core": {},
"sap.m": {},
"sap.ui.layout": {},
"sap.ui.table": {}
}
},
"contentDensities": {
"compact": true,
"cozy": true
},
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"settings": {
"bundleName": "treetable.i18n.i18n"
}
},
"testmodel": {
"type": "sap.ui.model.odata.v2.ODataModel",
"settings": {
"defaultOperationMode": "Server",
"defaultBindingMode": "OneWay",
"defaultCountMode": "Request"
},
"dataSource": "mainService",
"preload": true
}
},
"resources": {
"css": [
{
"uri": "css/style.css"
}
]
},
"routing": {
"config": {
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"async": true,
"viewPath": "treetable.view",
"controlAggregation": "pages",
"controlId": "app",
"clearControlAggregation": false
},
"routes": [
{
"name": "RoutetableView",
"pattern": "RoutetableView",
"target": ["TargettableView"]
}
],
"targets": {
"TargettableView": {
"viewType": "XML",
"transition": "slide",
"clearControlAggregation": false,
"viewId": "tableView",
"viewName": "tableView"
}
}
}
}
}
view.controller.js
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/core/UIComponent",
"sap/ui/model/odata/v2/ODataModel",
],
/**
* #param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller) {
"use strict";
return Controller.extend("treetable.controller.tableView", {
onInit: function () {
var oModel = this.getOwnerComponent().getModel("testmodel");
this.getView().setModel(oModel);
var oTreeTable = this.getView().byId("treeTable").setModel(oModel);
oTreeTable.bindRows({
path: "/NodeSet",
parameters : {
treeAnnotationProperties : {
hierarchyLevelFor : 'HierarchyLevel',
hierarchyNodeFor : 'NodeId',
hierarchyParentNodeFor : 'ParentNodeID',
hierarchyDrillStateFor : 'DrillState'} }
});
}
});
});
Your example should work as you expect, i converted it into a running example.
The only thing i change was NodeId to NodeID.
But i advice you to remove all this lines. Models which are define in the manifest are propagated automatically:
var oModel = this.getOwnerComponent().getModel("testmodel");
this.getView().setModel(oModel);
var oTreeTable = this.getView().byId("treeTable").setModel(oModel);
Also in the manifest.xml write "" instead of "testmodel". It is best practise to use the unnamed model for the odata-model.
Bindings are usually created, once the rounter is matching something. Doing it in onInit is also not best practise. see _onRouteMatched
sap.ui.require([
"sap/ui/core/util/MockServer"
], function(MockServer) {
var oMockServer = new MockServer({
rootUri: "/"
});
// simulate against the metadata and mock data
oMockServer.simulate(`<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:sap="http://www.sap.com/Protocols/SAPData">
<edmx:DataServices m:DataServiceVersion="2.0">
<Schema Namespace="Z_ODATA_EXAMPLE_SRV" xml:lang="en" sap:schema-version="1" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
<EntityType Name="Node" sap:content-version="1">
<Key>
<PropertyRef Name="NodeID"/>
</Key>
<Property Name="NodeID" Type="Edm.Int32" Nullable="false" sap:unicode="false" sap:label="ID" sap:hierarchy-node-for="NodeId"/>
<Property Name="HierarchyLevel" Type="Edm.Int32" Nullable="false" sap:unicode="false" sap:hierarchy-level-for="NodeId"/>
<Property Name="ParentNodeID" Type="Edm.Int32" sap:unicode="false" sap:hierarchy-parent-node-for="NodeId"/>
<Property Name="DrillState" Type="Edm.String" Nullable="false" MaxLength="8" sap:unicode="false" sap:hierarchy-drill-state-for="NodeId"/>
<Property Name="Description" Type="Edm.String" Nullable="false" MaxLength="80" sap:unicode="false"/>
</EntityType>
<EntityContainer Name="Z_ODATA_EXAMPLE_SRV_Entities" m:IsDefaultEntityContainer="true" sap:supported-formats="atom json xlsx">
<EntitySet Name="NodeSet" EntityType="Z_ODATA_EXAMPLE_SRV.Node" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:pageable="false" sap:content-version="1"/>
</EntityContainer>
<atom:link rel="self" href="https://dae:1234/sap/opu/odata/sap/Z_ODATA_EXAMPLE_SRV/$metadata" xmlns:atom="http://www.w3.org/2005/Atom"/>
<atom:link rel="latest-version" href="https://dae:1234/sap/opu/odata/sap/Z_ODATA_EXAMPLE_SRV/$metadata" xmlns:atom="http://www.w3.org/2005/Atom"/>
</Schema>
</edmx:DataServices>
</edmx:Edmx>`, {
bGenerateMissingMockData: true
});
oMockServer.setEntitySetData("NodeSet", [{
"__metadata": {
"uri": "NodeSet('1')"
},
"NodeID": 1,
"HierarchyLevel": 0,
"Description": "1",
"ParentNodeID": null,
"DrillState": "expanded"
},
{
"__metadata": {
"uri": "NodeSet('2')"
},
"NodeID": 2,
"HierarchyLevel": 0,
"Description": "2",
"ParentNodeID": null,
"DrillState": "expanded"
},
{
"__metadata": {
"uri": "NodeSet('3')"
},
"NodeID": 3,
"HierarchyLevel": 0,
"Description": "3",
"ParentNodeID": null,
"DrillState": "expanded"
},
{
"__metadata": {
"uri": "NodeSet('4')"
},
"NodeID": 4,
"HierarchyLevel": 1,
"Description": "1.1",
"ParentNodeID": 1,
"DrillState": "leaf"
},
{
"__metadata": {
"uri": "NodeSet('5')"
},
"NodeID": 5,
"HierarchyLevel": 1,
"Description": "1.2",
"ParentNodeID": 1,
"DrillState": "expanded"
}
])
// start
oMockServer.start();
const oModel = new sap.ui.model.odata.v2.ODataModel("/");
sap.ui.controller("view1.initial", {
onInit: function(oEvent) {
this.getView().setModel(oModel);
}
});
sap.ui.xmlview("main", {
viewContent: jQuery("#view1").html()
}).placeAt("uiArea");
});
<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-xx-bindingSyntax="complex" data-sap-ui-compatVersion="edge" data-sap-ui-debug="false" data-sap-ui-libs="sap.m"></script>
<div id="uiArea"></div>
<script id="view1" type="ui5/xmlview">
<mvc:View controllerName="view1.initial" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.ui.table" xmlns:m="sap.m">
<TreeTable id="treeTable" selectionMode="Single" enableColumnReordering="false" rows="{
path : '/NodeSet',
parameters : {
treeAnnotationProperties : {
hierarchyLevelFor : 'HierarchyLevel',
hierarchyNodeFor : 'NodeID',
hierarchyParentNodeFor : 'ParentNodeID',
hierarchyDrillStateFor : 'DrillState'
}
}
}">
<columns>
<Column label="Description">
<template>
<m:Text text="{Description}" wrapping="false" />
</template>
</Column>
<Column label="HierarchyLevel">
<template>
<m:Text text="{HierarchyLevel}" wrapping="false" />
</template>
</Column>
<Column label="NodeId">
<template>
<m:Text text="{NodeID}" wrapping="false" />
</template>
</Column>
<Column label="ParentNodeID">
<template>
<m:Text text="{ParentNodeID}" wrapping="false" />
</template>
</Column>
</columns>
</TreeTable>
</mvc:View>
</script>

ui5 sap.m.table dynamic binding using ODataModel

I have a struggling with my table and it's data, let me give you some context info, I'm using the version 1.72.3, my app is a standalone app hosted in a Nginx, all proxies are in place and working fine.
I have a View like a worklist (a view with one table) and I need to query the back-end using filters but JSONModel not allow it so my idea was simple
I create a propetry in JSONModel called "salesOrders"
using the event attachPatternMatched I call the back-end using oDataModel
I set the property "salesOrders" with the result of oDataModel's call
I bind my table to the property
I place all the code but my best result on screen was
This is the definition of my table in the view.
<Table noDataText="Drop column list items here and columns in the area above" items="{salesOrderListView>/salesOrders}"
id="tableSalesOrders" growingScrollToLoad="true" sticky="ColumnHeaders" growing="true">
<items>
<ColumnListItem type="Navigation" id="item0" press="onPressSalesOrder">
<cells>
<ObjectIdentifier xmlns="sap.m" title="{ path: 'Vbeln', formatter: '.formatter.numberNoZeros' }" titleActive="fasle" id="identifier0"/>
<Link xmlns="sap.m" text="{Customer/Name1}" id="link0" press="onPressCustomer"/>
<Link xmlns="sap.m" text="{Vendor/Ename}" id="link1" press="onPressVendor"/>
<core:Icon src="sap-icon://flag" size="2em" id="icon0" color="{ path: 'Lsstk', formatter: '.formatter.flagStatusColorC' }"/>
<core:Icon xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:core="sap.ui.core"
src="sap-icon://flag" size="2em" id="icon0_copy2" color="{ path: 'Cmgst', formatter: '.formatter.flagStatusColorCred' }"/>
<core:Icon xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:core="sap.ui.core"
src="sap-icon://flag" size="2em" id="icon0_copy" color="{ path: 'Lfstk', formatter: '.formatter.flagStatusColor' }"/>
<Text xmlns="sap.m" text="{Vdatu}" id="text1"/>
<ObjectNumber xmlns="sap.m" number="{ path: 'Kwmeng', formatter: '.formatter.numberNoDecimals' }" unit="CJ" id="number0" textAlign="Center"/>
<ObjectNumber xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns:html="http://www.w3.org/1999/xhtml" xmlns="sap.m"
number="{ path: 'Kwmengdlvy', formatter: '.formatter.numberNoDecimals' }" unit="CJ" id="number0_copy2" textAlign="Center"/>
<ObjectNumber xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns:html="http://www.w3.org/1999/xhtml" xmlns="sap.m"
number="{ path: 'Kwmengdiff', formatter: '.formatter.numberNoDecimals' }" unit="CJ" id="number0_copy" textAlign="Center"/></cells>
</ColumnListItem>
</items>
<columns>
<Column id="column0">
<header>
<Label text="{i18n>vbelnLabel}" id="label0"/>
</header>
</Column>
<Column id="column1" minScreenWidth="Large" demandPopin="true" popinDisplay="Inline">
<header>
<Label text="{i18n>customerName1Label}" id="label1"/>
</header>
</Column>
<Column id="column2" minScreenWidth="Large" demandPopin="true" popinDisplay="Inline" popinHAlign="Left">
<header>
<Label text="{i18n>vendorEnameLabel}" id="label2"/>
</header>
</Column>
<Column xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns:html="http://www.w3.org/1999/xhtml" xmlns="sap.m" id="column2_copy6"
demandPopin="true">
<header>
<Label text="Aprobación Comercial" id="label2_copy6" wrapping="true"/>
</header>
</Column>
<Column xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns:html="http://www.w3.org/1999/xhtml" xmlns="sap.m" id="column2_copy5"
demandPopin="true">
<header>
<Label text="Aprobación Crediticia" id="label2_copy5" wrapping="true"/>
</header>
</Column>
<Column xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns:html="http://www.w3.org/1999/xhtml" xmlns="sap.m" id="column2_copy4"
demandPopin="true">
<header>
<Label text="Expedición" id="label2_copy4"/>
</header>
</Column>
<Column xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns:html="http://www.w3.org/1999/xhtml" xmlns="sap.m" id="column2_copy2">
<header>
<Label text="{i18n>vdatuLabel}" id="label2_copy2" wrapping="true"/>
</header>
</Column>
<Column xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns:html="http://www.w3.org/1999/xhtml" xmlns="sap.m" id="column2_copy"
minScreenWidth="Large" demandPopin="true" popinDisplay="Inline">
<header>
<Label text="{i18n>kwmengLabel}" id="label2_copy" wrapping="true"/>
</header>
</Column>
<Column xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns:html="http://www.w3.org/1999/xhtml" xmlns="sap.m" id="column2_copy7"
demandPopin="true" minScreenWidth="Large" popinDisplay="Inline">
<header>
<Label text="{i18n>kwmengDlvyLabel}" id="label2_copy7" wrapping="true"/>
</header>
</Column>
<Column xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns:html="http://www.w3.org/1999/xhtml" xmlns="sap.m" id="column2_copy3">
<header>
<Label text="{i18n>kwmengDiffLabel}" id="label2_copy3" wrapping="true"/>
</header>
</Column>
</columns>
<headerToolbar>
<Toolbar width="100%" id="toolbar1">
<content>
<Title id="SalesOrderListHeader" text="{salesOrderView>/salesOrderTableTitle}"/>
<ToolbarSpacer/>
<SearchField id="searchField" tooltip="{i18n>salesOrderSearchTooltip}" search="onSearch" width="auto"/>
</content>
</Toolbar>
</headerToolbar>
</Table>
An in my controller I have this
sap.ui.define([
// "sap/ui/core/mvc/Controller",
"riders/polux/controller/BaseController",
"sap/ui/model/json/JSONModel",
"sap/ui/core/routing/History",
"riders/polux/model/formatter"
], function (BaseController, JSONModel, History, formatter) {
"use strict";
return BaseController.extend("riders.polux.controller.SalesOrderList", {
formatter: formatter,
/**
* Called when a controller is instantiated and its View controls (if available) are already created.
* Can be used to modify the View before it is displayed, to bind event handlers and do other one-time initialization.
* #memberOf riders.polux.view.SalesOrderList
*/
onInit: function () {
var headerTitle, oViewModel, iOriginalBusyDelay, oTable = this.byId("tableSalesOrders");
// Put down salesOrderList table's original value for busy indicator delay,
// so it can be restored later on. Busy handling on the table is
// taken care of by the table itself.
iOriginalBusyDelay = oTable.getBusyIndicatorDelay();
// Model used to manipulate control states
oViewModel = new JSONModel({
headerTitle: headerTitle,
queryMode: "", //queryMode,
tableBusyDelay: 0,
salesOrders: null
});
this.getRouter().getRoute("SalesOrderList").attachPatternMatched(this._onObjectMatched, this);
this.setModel(oViewModel, "salesOrderListView");
// Make sure, busy indication is showing immediately so there is no
// break after the busy indication for loading the view's meta data is
// ended (see promise 'oWhenMetadataIsLoaded' in AppController)
oTable.attachEventOnce("updateFinished", function () {
// Restore original busy indicator delay for salesOrderList's table
oViewModel.setProperty("/tableBusyDelay", iOriginalBusyDelay);
});
// Add the page to the flp routing history
},
_onObjectMatched: function (oEvent) {
var oViewModel = this.getModel("salesOrderListView");
var oTable = this.getView().byId("tableSalesOrders");
var headerTitle, oResourceBundle = this.getResourceBundle();
var queryMode = oEvent.getParameter("arguments").queryMode;
switch (queryMode) {
case "P":
headerTitle = oResourceBundle.getText("salesOrderListViewTitleP");
break;
case "H":
headerTitle = oResourceBundle.getText("salesOrderListViewTitleH");
break;
}
oViewModel.setProperty("/headerTitle", headerTitle);
this.addHistoryEntry({
title: headerTitle,
icon: "sap-icon://table-view",
intent: "#PortalPollux-display&/SalesOrderList/" + queryMode
}, true);
var salesOrders = oViewModel.getProperty("/salesOrders");
if (!salesOrders) {
var odata = new sap.ui.model.odata.v2.ODataModel("/sap/opu/odata/sap/ZPOLLUX_SRV/");
odata.read("/SalesOrderSet", {
success: function (oData, response) {
oViewModel.setData({
salesOrders: oData
}, true);
}
});
}
},
/*
*#memberOf riders.polux.controller.SalesOrderList
*/
onGoBack: function (oEvent) {
//This code was generated by the layout editor.
var oHistory = History.getInstance();
var sPreviousHash = oHistory.getPreviousHash();
// Go one screen back if you find a Hash
if (sPreviousHash !== undefined) {
window.history.go(-1);
}
// If you do not find a correct Hash, go to the Source screen using default router;
else {
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
oRouter.navTo("TargetLaunchpad", true);
}
},
onPressCustomer: function (oEvent) {
// The source is the list item that got pressed - custom
this._showObjectCustomer(oEvent.getSource());
},
onPressVendor: function (oEvent) {
// The source is the list item that got pressed - custom
this._showObjectVendor(oEvent.getSource());
},
onPressSalesOrder: function (oEvent) {
// The source is the list item that got pressed - custom
this._showObjectSalesOrder(oEvent.getSource());
},
_showObjectCustomer: function (oItem) {
this.getRouter().navTo("customer", {
objectId: oItem.getBindingContext().getProperty("Kunnr")
});
},
_showObjectVendor: function (oItem) {
this.getRouter().navTo("vendor", {
objectId: oItem.getBindingContext().getProperty("Pernr")
});
},
_showObjectSalesOrder: function (oItem) {
this.getRouter().navTo("RouteSalesOrder", {
objectId: oItem.getBindingContext().getProperty("Vbeln")
});
}
});
});
I'm fighting with this for two days and I can figure out where is my error.
Can somebody help me, please?
Best Regards and Thank you in advance
From my experience using a JSONModel as solution will introduce other problems:
- you only filter the datasets you fetched. But its likely you don't load them all
- no automatic loading indication, no error handling while loading
- complicated coding for operations on loaded datasets
My solution would be to grab the table binding and apply filters in the controller. However this can not be done in the init() function, since no table binding is set up. I usually use a navigation event that may carries a query parameter from the url that must be applied to the filters as well.
onInit: function() {
...
this.getRouter().getRoute("master").attachPatternMatched(this._onMasterMatched, this);
...
}
_onMasterMatched: function() {
var oList = this.byId("myTable");
oList.getBinding("items").filter(new Filter(...));
}
You bound your items property to the path salesOrderListView>/salesOrders, so you are using named model with the name salesOrderListView. At the same time your field binding path looks like Customer/Name1 and it actually point to an unnamed model. In your case it has to be like salesOrderListView>Customer/Name1
When you call odata.read you directly set the JSON model data by this:
oViewModel.setData({
salesOrders: oData
}, true);
but if you look at oData variable during debugging you will see that most probably it is not an array, it's an object with structure:
{ d: { results: [.....] } }
So, I would try to assign data to the model this way:
oViewModel.setData({
salesOrders: oData.d.results
}, true);

How to bind oData to table with parameter

I have oData by path Northwind Customers('ANATR')/Orders
I can't bind it to table Customer orders
Here I have /Customers('" + oArgs.customerId + "')/Orders like in oData link
OrderList.controller.js
sap.ui.define([
"sap/ui/demo/nav/controller/BaseController"
], function (BaseController) {
"use strict";
return BaseController.extend("sap.ui.demo.nav.controller.customer.OrderList", {
onInit: function () {
var oRouter = this.getRouter();
oRouter.getRoute("customer").attachMatched(this._onRouteMatched, this);
},
_onRouteMatched : function (oEvent) {
var oArgs, oView;
oArgs = oEvent.getParameter("arguments");
oView = this.getView();
oView.bindElement({
path : "/Customers('" + oArgs.customerId + "')/Orders",
events : {
change: this._onBindingChange.bind(this),
dataRequested: function (oEvent) {
oView.setBusy(true);
},
dataReceived: function (oEvent) {
oView.setBusy(false);
}
}
});
}
});
});
And here I link it to bind data {path : '/Orders'} how to insert {CustomerID} parameter?
OrderList.view.xml
<mvc:View
controllerName="sap.ui.demo.nav.controller.customer.OrderList"
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns:f="sap.ui.layout.form"
xmlns:core="sap.ui.core">
<Page
id="orderListPage"
title="{i18n>OrderList}"
showNavButton="true"
navButtonPress=".onNavBack"
class="sapUiResponsiveContentPadding">
<Panel accessibleRole="Region">
<headerToolbar>
<Toolbar>
<Title text="{i18n>orderListTitle}"/>
<ToolbarSpacer/>
<SearchField
width="50%"
search=".onFilterOrders"/>
</Toolbar>
</headerToolbar>
<Table
id="orderList"
class="sapUiResponsiveMargin"
width="auto"
items="{
path : '/Orders'
}">
<columns>
<Column
hAlign="End"
minScreenWidth="Small"
demandPopin="true"
width="4em">
<Text text="{i18n>columnOrderID}"/>
</Column>
<Column>
<Text text="{i18n>columnCustomerID}"/>
</Column>
<Column
minScreenWidth="Tablet"
demandPopin="false">
<Text text="{i18n>columnOrderDate}"/>
</Column>
<Column
hAlign="End">
<Text text="{i18n>columnPrice}"/>
</Column>
</columns>
<items>
<ColumnListItem
type="Navigation"
press=".onPress">
<cells>
<ObjectNumber number="{OrderID}" emphasized="false"/>
<ObjectIdentifier title="{CustomerID}"/>
<Text text="{OrderDate}"/>
<ObjectNumber
number="{
parts: [{path: 'Freight'}],
type: 'sap.ui.model.type.Currency',
formatOptions: {
showMeasure: false
}
}"/>
</cells>
</ColumnListItem>
</items>
</Table>
</Panel>
</Page>
</mvc:View>
path : '/Orders' is an absolute binding (slash at the beginning). This means UI5 will try to fetch https://services.odata.org/V2/Northwind/Northwind.svc/Orders.
Also you bound your view to a list of things. In general, this is not what you want.
What you want is to bind your view against a single Customer entity
oView.bindElement({
path : "/Customers('" + oArgs.customerId + "')",
events: {
...
}
});
and then use relative binding (no slash at the beginning) for the Orders:
items="{
path : 'Orders'
}"

sap.m.table does not get updated

I have a tab in a view including a table (declared in the XML view) supposed to be populated with the press of a button. Button attaches some filters and calls the model.read() method which returns results successfully. However the table remains empty.
I know that the XML view binding is correct because before using the button logic populated some data via a hard-coded call in Component.js and data appeared as expected.
I know also that the data are coming back, debugged at the end of the function and all data are there. I tried even refreshing the model with the bForceUpdate parameter set to "true" at the end of the function but no luck either. Code in doubt and the table part of the XML view is below.
Controller function code - only filter manipulation above
if ( sYearFmParam === "" || sYearToParam === "" ) {
MessageBox.error(
this.getModel("i18n").getResourceBundle().getText("fiscalYearEmptyErrorMesage"),
{
actions: [MessageBox.Action.CLOSE]
}
);
} else if ( sYearFmKey <= sYearToKey ) {
if (sYearDiff < 15) {
this.oReportModel.read(sPath, { filters: oTableSearchState,
success: function(oData, oResponse) {
oStsReportDataDeferred.resolve();
},
error: function(oError) {
jQuery.sap.log.error("Error", oError);
}
});
} else {
MessageBox.error(
this.getModel("i18n").getResourceBundle().getText("fiscalYearDiffErrorMesage"),
{
actions: [MessageBox.Action.CLOSE]
}
);
}
} else {
MessageBox.error(
this.getModel("i18n").getResourceBundle().getText("fiscalYearErrorMesage"),
{
actions: [MessageBox.Action.CLOSE]
}
);
}
var readyToGo = function() {
this.oReportModel.refresh(true);
this.getModel("Global").setProperty("/statusTableVisible", true);
jQuery.sap.log.debug("report refreshed");
};
jQuery.when(oStsReportDataDeferred).done().then( jQuery.proxy(readyToGo, this) );
XML view - only the table part
<Table id="statusReportTable"
items="{
path: 'Report>/Status_Report_DataSet',
sorter: { path: 'ReportBy' }
}"
width="auto"
class="sapUiResponsiveMargin"
noDataText="{worklistView>/tableNoDataText}"
busyIndicatorDelay="{worklistView>/tableBusyDelay}"
growing="true"
growingScrollToLoad="true"
visible="{Global>/statusTableVisible}">
<headerToolbar>
<Toolbar>
<Title id="statusReportToolbar" text="{worklistView>/summaryTableTitle}"/>
<ToolbarSpacer />
</Toolbar>
</headerToolbar>
<columns>
<Column></Column>
<Column></Column>
<Column></Column>
<Column></Column>
<Column></Column>
<Column></Column>
<Column></Column>
<Column></Column>
<Column></Column>
<Column></Column>
<Column></Column>
<Column></Column>
<Column></Column>
<Column></Column>
<Column></Column>
</columns>
<items>
<ColumnListItem>
<cells>
<Text text="{Report>ReportBy}" width="100px"/>
<Text text="{path: 'Report>StsStarted1'}" width="40px"
visible="{path: 'Report>StsStarted1v', formatter: '.formatter.setStatusColumnVisibility'}"/>
<Text text="{path: 'Report>Sts0041'}" width="40px"
visible="{path: 'Report>Sts0041v', formatter: '.formatter.setStatusColumnVisibility'}"/>
<Text text="{path: 'Report>Sts0021'}" width="40px"
visible="{path: 'Report>Sts0021v', formatter: '.formatter.setStatusColumnVisibility'}"/>
<Text text="{path: 'Report>Sts0031'}" width="40px"
visible="{path: 'Report>Sts0031v', formatter: '.formatter.setStatusColumnVisibility'}"/>
<Text text="{path: 'Report>StsAct1'}" width="40px"
visible="{path: 'Report>StsAct1v', formatter: '.formatter.setStatusColumnVisibility'}"/>
<Text text="{path: 'Report>Sts0011'}" width="40px"
visible="{path: 'Report>Sts0011v', formatter: '.formatter.setStatusColumnVisibility'}"/>
<Text text="{path: 'Report>Sts0061'}" width="40px"
visible="{path: 'Report>Sts0061v', formatter: '.formatter.setStatusColumnVisibility'}"/>
<Text text="{path: 'Report>StsStarted2'}" width="40px"
visible="{path: 'Report>StsStarted2v', formatter: '.formatter.setStatusColumnVisibility'}"/>
<Text text="{path: 'Report>Sts0042'}" width="40px"
visible="{path: 'Report>Sts0042v', formatter: '.formatter.setStatusColumnVisibility'}"/>
<Text text="{path: 'Report>Sts0022'}" width="40px"
visible="{path: 'Report>Sts0022v', formatter: '.formatter.setStatusColumnVisibility'}"/>
<Text text="{path: 'Report>Sts0032'}" width="40px"
visible="{path: 'Report>Sts0032v', formatter: '.formatter.setStatusColumnVisibility'}"/>
<Text text="{path: 'Report>StsAct2'}" width="40px"
visible="{path: 'Report>StsAct2v', formatter: '.formatter.setStatusColumnVisibility'}"/>
<Text text="{path: 'Report>Sts0012'}" width="40px"
visible="{path: 'Report>Sts0012v', formatter: '.formatter.setStatusColumnVisibility'}"/>
<Text text="{path: 'Report>Sts0062'}" width="40px"
visible="{path: 'Report>Sts0062v', formatter: '.formatter.setStatusColumnVisibility'}"/>
</cells>
</ColumnListItem>
</items>
</Table>
I can't really say why your table does not display anything, but I can notice that you are not using the OData model completely correctly regarding the filtering. Looking at the table items' binding from the XML view, I would expect that the table displays all the entities from the Status_Report_DataSet entity set. If it is not the case then either the backend OData service returns no entities at all if you attempt to read the whole entity set or the binding is suspended in your controller manually.
The OData model (and the whole model concept in UI5 in general) requires you to add the filters to the binding of the table. Doing programmatic read calls does not affect the table contents. The correct way of doing it would be:
this.byId("statusReportTable").getBinding("items").filter(oTableSearchState);
Also, doing a model refresh will simply re-trigger one or more read requests for all the bound entity sets or individual entities.

Resources