Search code examples
annotationsodatasapui5

How to show complex OData property types in sap.ui.comp.smarttable.SmartTable?


I'm working on a SAPUI5 application and want to display a list of data records using a sap.ui.comp.smarttable.SmartTable.

Fiddling around with the Smart Table samples from the SAPUI5 Explored App I was able to get the Smart Table running against an OData service provided by a mock server.

Smart Table in XML view

<smartTable:SmartTable tableType="ResponsiveTable"
    entitySet="RecordSet" enableAutoBinding="true" />

Corresponding lines of metadata.xml

<Schema Namespace="my.namespace" sap:schema-version="1" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">

    <ComplexType Name="ShortReference">
        <Property Name="Type" Type="Edm.String" Nullable="false" sap:label="Reference type" />
        <Property Name="Key" Type="Edm.String" Nullable="false" sap:label="Reference key" />
    </ComplexType>

    <EntityType Name="Record" sap:label="Record" sap:content-version="1">
        <Key>
            <PropertyRef Name="RecordID" />
        </Key>
        <Property Name="RecordID" Type="Edm.String" Nullable="false" sap:label="Record ID" sap:creatable="false" sap:updatable="false" />
        <Property Name="ShortReference" Type="my.namespace.ShortReference" />
    </EntityType>

    <EntityContainer Name="my.namespace.Entities" m:IsDefaultEntityContainer="true" sap:supported-formats="atom json xlsx">
        <EntitySet Name="RecordSet" EntityType="my.namespace.Record" />
    </EntityContainer>

    <!-- Default columns shown by Smart Table -->
    <Annotations Target="my.namespace.Record" xmlns="http://docs.oasis-open.org/odata/ns/edm">
        <Annotation Term="com.sap.vocabularies.UI.v1.LineItem">
            <Collection>
                <Record Type="com.sap.vocabularies.UI.v1.DataField">
                    <PropertyValue Property="Value" Path="RecordID" />
                </Record>
                <!-- The following doesn't work - it won't be shown in a Smart Table column -->
                <Record Type="com.sap.vocabularies.UI.v1.DataField">
                    <PropertyValue Property="Value" Path="ShortReference/Key" />
                </Record>
                <Record Type="com.sap.vocabularies.UI.v1.DataField">
                    <PropertyValue Property="Value" Path="ShortReference/Type" />
                </Record>
            </Collection>
        </Annotation>
    </Annotations>
</Schema>

As you can see a data record has a complex property of type my.namespace.ShortReference. I want the two properties to appear in the Smart Table as separate columns to be able to filter them.

I did have little success by using the <customData> aggregation as follows, but as I'm having more than this single complex entity (including a complex entity with another complex entity) I'm searching for a simpler and more robust way to achive that goal. Furthermore, with <customData> my filtering ability in the p13n dialog is limited (no possibility to use filter like contains, starts with etc.).

Smart Table with custom data

<smartTable:SmartTable tableType="ResponsiveTable"
    entitySet="RecordSet" enableAutoBinding="true" >
    <Table>
        <!-- http://stackoverflow.com/questions/32114675/sapui5-smart-table-how-to-inject-my-own-column-into-smart-table-default-colum -->
        <!-- Smart Table Developer Guide: https://sapui5.hana.ondemand.com/#docs/guide/bed8274140d04fc0b9bcb2db42d8bac2.html -->
        <columns>
            <!-- Reference -->
            <Column>
                <customData>
                    <core:CustomData
                        key="p13nData"
                        value='\{
                            "columnKey":        "ReferenceType",
                            "leadingProperty":  "ShortReference/Type",
                            "sortProperty":     "ShortReference/Type",
                            "filterProperty":   "ShortReference/Type",
                            "columnIndex":      "9"
                        }' />
                </customData>
                <Label text="Reference type"/>
            </Column>
            <Column>
                <customData>
                    <core:CustomData
                        key="p13nData"
                        value='\{
                            "columnKey":        "ReferenceKey",
                            "leadingProperty":  "ShortReference/Key",
                            "sortProperty":     "ShortReference/Key",
                            "filterProperty":   "ShortReference/Key",
                            "columnIndex":      "10"
                        }' />
                </customData>
                <Label text="Reference key"/>
            </Column>
        </columns>
        <items>
            <ColumnListItem>
                <cells>
                    <Text text="{ShortReference/Type}" />
                    <Text text="{ShortReference/Key}" />
                </cells>
            </ColumnListItem>
        </items>
    </Table>
</smartTable:SmartTable>

So, is this even possible to achieve? Or do I have to flatten my OData entity?

I would also change to a normal sap.m.Table if it's easier. I have chosen the Smart Table because of it's sorting, filtering, grouping abilities and the variant management (I need all of those).


Solution

  • I have searched for a solution for a while, but I haven't found a satisfactory solution matching my entity structure above.

    Therefore I have to answer my questions as follows

    • So, is this even possible to achieve? No.
    • Or do I have to flatten my OData entity? Yes.

    My list gives an overview over a specific record set an navigates to a detail page. In my overview list I don't need every property, so I have created a new entity RecordOverview to run my Smart Table against.

    metadata.xml (showing additions and changes only)

    <Schema Namespace="my.namespace" sap:schema-version="1" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
    
        ...
    
        <EntityType Name="RecordOverview" sap:label="Record" sap:content-version="1">
            <Key>
                <PropertyRef Name="RecordID" />
            </Key>
            <Property Name="RecordID" Type="Edm.String" Nullable="false" sap:label="Record ID" sap:creatable="false" sap:updatable="false" />
            <Property Name="ReferenceKey" Type="Edm.String" Nullable="false" sap:label="Reference key" />
        </EntityType>
    
        <EntityContainer Name="my.namespace.Entities" m:IsDefaultEntityContainer="true" sap:supported-formats="atom json xlsx">
            <EntitySet Name="RecordSet" EntityType="my.namespace.Record" />
            <EntitySet Name="RecordOverviewSet" EntityType="my.namespace.RecordOverview" />
        </EntityContainer>
    
        <!-- Default columns shown by Smart Table -->
        <Annotations Target="my.namespace.RecordOverview" xmlns="http://docs.oasis-open.org/odata/ns/edm">
            <Annotation Term="com.sap.vocabularies.UI.v1.LineItem">
                <Collection>
                    <Record Type="com.sap.vocabularies.UI.v1.DataField">
                        <PropertyValue Property="Value" Path="RecordID" />
                    </Record>
                    <Record Type="com.sap.vocabularies.UI.v1.DataField">
                        <PropertyValue Property="Value" Path="ReferenceKey" />
                    </Record>
                    ...
                </Collection>
            </Annotation>
        </Annotations>
    </Schema>
    

    However, a nice (side) effect is I don't need to specify the columns in my XML view anymore.

    XML view

    <smartTable:SmartTable entitySet="RecordOverviewSet" enableAutoBinding="true">
        <Table>
            <items>
                <ColumnListItem vAlign="Middle" type="Navigation" press="onListItemPressed" />
            </items>
        </Table>
    </smartTable:SmartTable>