Skip to Content
Technical Articles
Author's profile photo Péter Catano

SAPUI5 Smart features controlled by OData Annotations

Hi,

In this post I want to give an insight into metadata based UI development. I will showcase some of the Smart component features controlled by metadata annotations. With the use of annotations and Smart components like SmartTable you can minimize the UI View code to be written for conventional scenarios like listing and filtering data.

Example1: Listing EntitySet with SmartTable

Given the following model with Products EntitySet: (from OData v2 Reference Service)

<Schema Namespace="ODataDemoService" xmlns="http://schemas.microsoft.com/ado/2007/05/edm"
            xmlns:sap="http://www.sap.com/Protocols/SAPData">
    <EntityType Name="Product">
        <Key>
            <PropertyRef Name="ID"/>
        </Key>
        <Property Name="ID" Type="Edm.Int32" Nullable="false" sap:label="ID"/>
        <Property Name="CategoryID" Type="Edm.Int32" Nullable="false" sap:label="Category"/>
        <Property Name="SupplierID" Type="Edm.Int32" Nullable="false" sap:label="Supplier"/>
        <Property Name="Name" Type="Edm.String" Nullable="true" sap:label="Name"/>
        <NavigationProperty Name="Supplier" Relationship="ODataDemo.Product_Supplier_Supplier_Products" FromRole="Product_Supplier"
            ToRole="Supplier_Products"/>		
    </EntityType>
	<EntityContainer Name="DemoService" m:IsDefaultEntityContainer="true">
		<EntitySet Name="Products" EntityType="ODataDemoService.Product" />
		</EntitySet>
	</EntityContainer>
</Schema>

and the following UI View with a SmartFilter and SmartTable component listing the Products entitySet:

<smartFilterBar:SmartFilterBar id="smartFilterBar" entitySet="Products" 
    useToolbar="false" showFilterConfiguration="false">
</smartFilterBar:SmartFilterBar>
<smartTable:SmartTable id="ProductsSmartTable" entitySet="Products" 
    smartFilterId="smartFilterBar" header="Products" showRowCount="true"
    useExportToExcel="false" useVariantManagement="false" 
    useTablePersonalisation="false">
</smartTable:SmartTable>

Running the application and pressing ‘Go’ in the smartFilterBar will give an error message:

It’s because no descriptor exists that describes how Products should be listed.

Resolution:

To select columns for smartTable, use LineItem annotation. It applies to EntityTypes, and it is a collection of data fields for representation in a table or list: (for documentations see Appendix1: Annotations, on how to add annotations see Appendix2: Adding annotations to metadata)

<Annotations Target="ODataDemoService.Product">
    <Annotation Term="com.sap.vocabularies.UI.v1.LineItem">
        <Collection>
            <Record Type="com.sap.vocabularies.UI.v1.DataField">
                <PropertyValue Property="Value" Path="Name"/>
            </Record>
            <Record Type="com.sap.vocabularies.UI.v1.DataField">
                <PropertyValue Property="Value" Path="CategoryID"/>
            </Record>
            <Record Type="com.sap.vocabularies.UI.v1.DataField">
                <PropertyValue Property="Label" String="Supplier Name"/>
                <PropertyValue Property="Value" Path="Supplier/Name"/>
            </Record>
        </Collection>
    </Annotation>
</Annotations>

Data fields are value paths pointing to properties of our entityType, navigationProperties can be used as path too.

With annotations added filtering again in the UI will list items successfully:

Notice that no additional View code had to be written, only adding annotations to our model.

Self test: add or remove some more columns by adding/removing data fields under LineItem annotation and observe smartTable changing according to it

Example2: Adding Value Help to SmartFilterBar control

Given the following model with Products and Categories entitySets:

<EntityType Name="Product">
    <Key>
        <PropertyRef Name="ID"/>
    </Key>
    <Property Name="ID" Type="Edm.Int32" Nullable="false" sap:label="ID"/>
    <Property Name="CategoryID" Type="Edm.Int32" Nullable="false" 
        sap:label="Category"/>
</EntityType>
<EntityType Name="Category">
    <Key>
        <PropertyRef Name="ID"/>
    </Key>
    <Property Name="ID" Type="Edm.Int32" Nullable="false" sap:label="ID"/>
    <Property Name="Name" Type="Edm.String" Nullable="true" 
        sap:label="Name"/>
</EntityType>
<EntityContainer Name="DemoService" m:IsDefaultEntityContainer="true">
    <EntitySet Name="Products" EntityType="ODataDemoService.Product" />
    <EntitySet Name="Categories" EntityType="ODataDemoService.Category" />
</EntityContainer>

and the UI View with smartFilter and smartTable components listing the Products entitySet with a CategoryID filter:

<smartFilterBar:SmartFilterBar id="smartFilterBar" entitySet="Products" 
    useToolbar="false" showFilterConfiguration="false">
    <smartFilterBar:controlConfiguration>
        <smartFilterBar:ControlConfiguration key="CategoryID" 
            visibleInAdvancedArea="true"
            preventInitialDataFetchInValueHelpDialog="false">
        </smartFilterBar:ControlConfiguration>
    </smartFilterBar:controlConfiguration>
</smartFilterBar:SmartFilterBar>
<smartTable:SmartTable id="ProductsSmartTable" entitySet="Products" 
    smartFilterId="smartFilterBar" header="Products" showRowCount="true"
    useExportToExcel="false" useVariantManagement="false" 
    useTablePersonalisation="false" tableType="ResponsiveTable">
</smartTable:SmartTable>

In the UI CategoryID filter has a built in value help. By default, the framework recognizes CategoryID type as described in the metadata model: Int32. Pressing Value Help icon displays value help popup where filter conditions can be defined for CategoryID as Int32 number: (equal to, between, less than, …)

Resolution:

To list an entitySet as possible values for a property, use ValueList annotation. It applies to property or parameter, and specifies how to get a list of acceptable values for such property or parameter: (for documentations see Appendix1: Annotations, on how to add annotations see Appendix2: Adding annotations to metadata)

<Annotations Target="ODataDemoService.Product/CategoryID">
    <Annotation Term="com.sap.vocabularies.Common.v1.ValueList">
        <Record Type="com.sap.vocabularies.Common.v1.ValueListType">
            <PropertyValue Property="CollectionPath" String="Categories"/>
            <PropertyValue Property="Parameters">
                <Collection>
                    <Record Type="com.sap.vocabularies.Common.v1.ValueListParameterOut">
                        <PropertyValue Property="LocalDataProperty" PropertyPath="CategoryID"/>
                        <PropertyValue Property="ValueListProperty" String="ID"/>
                    </Record>
                    <Record Type="com.sap.vocabularies.Common.v1.ValueListParameterDisplayOnly">
                        <PropertyValue Property="ValueListProperty" String="Name"/>
                    </Record>
                </Collection>
            </PropertyValue>
        </Record>
    </Annotation>
</Annotations>

 

By adding ValueList annotation the automatic value help of CategoryID filter lists Categories as possible values for CategoryID:

Example3: Add Value Help as a Dropdown List to SmartFilterBar control

Let’s extend Example2 model with the following SAP Annotations for Product/CategoryID:

sap:value-list=”fixed-values”

It’s a string indicating whether this property has a value list attached:

  • fixed-values – there is a short list of allowed field values that rarely changes over time
  • standard (default) – no restriction on number and volatility of allowed field values

The list of allowed values is provided as a separate entity set that can be found by interpreting the V4-style annotation Common.ValueList on the same property.

(for documentations see Appendix1: Annotations, on how to add annotation see Appendix2: Adding annotations to metadata)

<EntityType Name="Product">
    <Key>
        <PropertyRef Name="ID"/>
    </Key>
    <Property Name="ID" Type="Edm.Int32" Nullable="false" sap:label="ID"/>
    <Property Name="CategoryID" Type="Edm.Int32" Nullable="false" sap:label="Category" 
        sap:value-list="fixed-values"/>
</EntityType>

CategoryID filter changed from standard value help dialog to dropdown list:

Example4: Display Text value instead of ID in Dropdown List

To display a human readable text value instead of ID, a reference can be defined for entityType properties. Let’s try this on Example3, extending our Category/ID property with the following annotation:

sap:text=”Name”

It’s a path expression that identifies a property in the context of the entity type containing a human-readable text for the value of this property.

(for documentations see Appendix1: Annotations, on how to add annotation see Appendix2: Adding annotations to metadata)

<EntityType Name="Category">
    <Key>
        <PropertyRef Name="ID"/>
    </Key>
    <Property Name="ID" Type="Edm.Int32" Nullable="false" sap:text="Name" sap:label="ID"/>
    <Property Name="Name" Type="Edm.String" Nullable="true" sap:label="Name"/>
</EntityType>                

In the UI we see that Name value displayed instead of ID:

Notice that this is just a display option, in the background CategoryID property will be sent to server not the Name property when filtering Products, which is the desired behaviour.

Appendix1: Annotations

Let’s take a look at the following annotations:

SAP Annotations for OData Version 2.0

These annotation are element properties from the http://www.sap.com/Protocols/SAPData namespace. Properties can be added to metadata for elements edm:Schema, edm:EntityContainer, edm:EntitySet, edm:EntityType, edm:Property, edm:NavigationProperty, edm:FunctionImport, edm:Parameter, edm:AssociationSet.
Example: (edm:Property)

<Schema Namespace="ODataDemoService" xmlns="http://schemas.microsoft.com/ado/2007/05/edm"
            xmlns:sap="http://www.sap.com/Protocols/SAPData">
    <EntityType Name="Product">
        <Key>
            <PropertyRef Name="ID"/>
        </Key>
        <Property Name="ID" Type="Edm.Int32" Nullable="false" sap:label="ID" sap:text="Name"/>
        <Property Name="CategoryID" Type="Edm.Int32" Nullable="false" sap:label="Category" sap:value-list="fixed-values"/>
        <Property Name="SupplierID" Type="Edm.Int32" Nullable="false" sap:label="Supplier" sap:value-list="standard"/>
        <Property Name="Name" Type="Edm.String" Nullable="true" sap:label="Name"/>
    </EntityType>
</Schema>

OData 4.0 Vocabularies

These annotations are Annotations elements from the http://schemas.microsoft.com/ado/2008/09/edm namespace.

Annotations elements has to be placed under the same Schema (same Namespace) as the OData service EntityType and EntityContainer elements. Can be placed into the same metadata.xml file or in a separate annotation file.
Example:

<edmx:Edmx 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" Version="1.0">
    <edmx:DataServices m:DataServiceVersion="2.0">
        <Schema xmlns="http://schemas.microsoft.com/ado/2008/09/edm"
                Namespace="ODataDemoService" xml:lang="en" sap:schema-version="1">
            <Annotations Target="ODataDemoService.Product"
                    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="Name"/>
                        </Record>
                    </Collection>
                </Annotation>
            </Annotations>
        </Schema>
    </edmx:DataServices>
</edmx:Edmx>            

Appendix2: Adding annotations to metadata

Metadata can be extended with annotations in different places of the application.

SAPUI5

In the UI client, the server side metadata descriptor can be extended with OData 4.0 Vocabularies in a separate file. Annotation file then needs to be referenced in manifest:

"sap.app": {
    "dataSources": {
        "mainService": {
            "uri": "/here/goes/your/serviceurl/",
            "type": "OData",
            "settings": {
                "localUri": "localService/metadata.xml",
                "annotations": [
                    "annotation0"
                ]
            }
        },
        "annotation0": {
            "type": "ODataAnnotation",
            "uri": "annotation0.xml",
            "settings": {
                "localUri": "annotation0.xml"
            }
        }
    }
}

With the use of WebIDE annotation file can be generated by right clikcking webapp and select New > “Annotation File”. Annotation file and the reference to the OData service in manifest will be created:

“Annotation Modeler” is a great visual editor for annotations:

ABAP

SAP Annotations

Annotations can be added in the DEFINE method of the Model Provider Extension class MPC_EXT:

DATA:
    lo_annotation   TYPE REF TO /iwbep/if_mgw_odata_annotation,
    lo_property     TYPE REF TO /iwbep/if_mgw_odata_property.

    lo_annotation->add( iv_key = 'semantics' iv_value = 'fixed-values').
    lo_property = model->get_entity_type('Product')->get_property('CategoryID').
    lo_property->set_value_list( /iwbep/if_mgw_odata_property=>gcs_value_list_type_property-fixed_values ).

Vocabularies

Annotations can be added in the DEFINE method of the Model Provider Extension class MPC_EXT:

DATA: 
    lo_ann_target  TYPE REF TO /iwbep/if_mgw_vocan_ann_target,
    lo_annotation  TYPE REF TO /iwbep/if_mgw_vocan_annotation,
    lo_collection  TYPE REF TO /iwbep/if_mgw_vocan_collection,
    lo_record      TYPE REF TO /iwbep/if_mgw_vocan_record,    
    lo_property    TYPE REF TO /iwbep/if_mgw_vocan_property,  
    lo_simp_value  TYPE REF TO /iwbep/if_mgw_vocan_simple_val.

    " annotations for entity type Product
    lo_ann_target = vocab_anno_model->create_annotations_target( 'Product' ).
    lo_ann_target->set_namespace_qualifier( 'ODataDemoService' ).
    
    " Columns to be displayed by default
    lo_annotation = lo_ann_target->create_annotation( iv_term = 'UI.LineItem' ).
    lo_collection = lo_annotation->create_collection( ).

    lo_record = lo_collection->create_record( iv_record_type = 'UI.DataField' ).
    lo_property = lo_record->create_property( 'Value' ).
    lo_simp_value = lo_property->create_simple_value( ).
    lo_simp_value->set_path( 'Name' ).    

CDS

CDS Annotations

@OData.publish: true
define view Z_Products
	as select from Products
{
	key Products.ID,
	@UI: {
		lineItem: {position: 20}
	}
	Products.Name
}

Conclusion

With the use of Smart components UI behaviour can be controlled by metadata annotations without modifing the UI View code. We saw examples of smart features, and ways to extend metadata with annotations.

Regards,

Peter

Assigned Tags

      13 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Ravikanth Tunuguntla
      Ravikanth Tunuguntla

      Great article Peter.. I am trying to explore exactly these features. Thanks for the article.

      I have a question, I am generating oData service from CDS (ABAP 7.50). I want to make one selection field  that should be displayed in smart filter bar as a dropdown (with dropdown values coming from a domain). What CDS annotation I have to provide for that field in CDS so that it will generate the annotation “sap:value-list=”fixed-values” in the metadata file?

      Thanks

      Ravikanth

      Author's profile photo Péter Catano
      Péter Catano
      Blog Post Author

      Hi Ravikanth Tunuguntla

      As far as I know, you have to add the fixed-value annotation in the model provider class of your service.

      Please check the following blogpost:

      How to build drop down list based on fixed value defined in a domain | SAP Blogs

      Regards,

      Peter

      Author's profile photo Prajesh Desai
      Prajesh Desai

      Hi Peter,

      Thanks for this useful blog.

      I do have one wonder with Example 4.

      How to add both (ID and Name) in value list?. Like this example.

      Thanks in advance.

      Best Regards,

      Prajesh

      Author's profile photo Péter Catano
      Péter Catano
      Blog Post Author

      Hi Prajesh Desai ,

      Thanks for your question. Sorry for the delayed answer.

      The element used in the example you mentioned is ListItem.

      I would try to search for an annotation in

      I never did something like that before, but it is an interesting question.

      Please let me know if you suceed.

      Regards,

      Peter

      Author's profile photo Juan Jose Madrid Amezcua
      Juan Jose Madrid Amezcua

      You just need to add this property to the XML

      <smartFilterBar:ControlConfiguration displayBehaviour="descriptionAndId" .../>

       

      displayBehaviour

       

      Best Regards,

      JJ

      Author's profile photo Juan Jose Madrid Amezcua
      Juan Jose Madrid Amezcua

      Extremely  useful!! thanks you very much Péter!

      Author's profile photo Victor Klein
      Victor Klein

      Hi Péter Catano,

      thanks for this blog post! It is very helpfull!

      But for me, there is still one question left:

      Does the ValueHelp for the SmartFilterBar only work in combination with a SmartTable or I can use SmartFilterBar with ValueHelp in a standalone way?

       

      Kind regards!

      Author's profile photo Péter Catano
      Péter Catano
      Blog Post Author

      Hi Victor Klein

      Thank you for your comment, I'm glad you find the post helpful.

      Take a look at the SmartFilterBar examples here, I think the filter only makes sense in conjunction with a table control.

      Probably the component for the functionality you are searching for can be SmartFiled? It is also a smart control, but we can call it "standalone".

      Let me know if I understood well your question.

      Regards,

      Peter

      Author's profile photo Victor Klein
      Victor Klein

      Hi Péter Catano,

      i will specify my idea. I want to use SmartFilterBar and Smart VariantManagement in my

      applikation. To avoide writing UI-Code for for each CustomFilter of SmartFilterBar I would like to use

      ValueHelp to consume data via Annotations straight from the metadata. Therefore I would like to

      use SmartFilterBar standalone and is it possible to use ValueHelp without a SmartTable?

       

       

      I hope this makes everything clearer.

      Kind Regards

       

      Author's profile photo Péter Catano
      Péter Catano
      Blog Post Author

      Hi Victor Klein

      I think I see your point.

      Probably the name of the component could be confusing. In general, "Smart" components are the ones whose behaviour is controlled by Annotations. The "FilterBar" part in the name of SmartFilterBar means that it is a bar element on top of the Table and filter in meaning of "contains filter elements for the table" which could be a DatePicker, a Text input, Dropdown or in your case an input with ValueHelp. We have this very same ValueHelp functionality in another smart component, called Smart Filed.

      Please check this examples:

      If this is what you mean, I will try to add another topic to the blog post for SmartFields.

      Also, please check the topic Developing Apps with SAP Fiori Elements - Documentation - Demo Kit - SAPUI5 SDK which is another way to develop UI application driven by OData metadata.

      Cheers,

      Peter

      Author's profile photo Victor Klein
      Victor Klein

      Hi Péter Catano,

      thanks for your quick response! So far I see no difference in using a SmartField with ValueHelp 

      and "smartFilterBar:ControlConfiguration" with ValueHelp. Both

      Those Smart Components are controlled by the same Annotations, aren't they?

      I would appreciate an extension about SmartFields  to see the possible differences between

      SmartFilterBar and SmartFields.

      Thanks in advance!

      Regards
      Victor

       

      Author's profile photo Ramin Shafai
      Ramin Shafai

      I have a property for which I define a ValueListParameterIn annotation, to filter the list in Value Help. It works perfectly.

      As soon as I change the value list to FixedValues, the ValueListParameterIn annotation is ignored.

      Are parameterIn/Out not supported for FixedValue . helps?

      I can't find any documentation on this restriction.

       

      Thanks.

      Author's profile photo Péter Catano
      Péter Catano
      Blog Post Author

      Hello Ramin Shafai ,

      Thank you for your question.

      May I ask what is the error symptom you are experiencing?

      Example 3 uses ValueListParamaterOut with fixed-values, can you confirm that it works that way in your case?
      Can you possibly use it that way in your scenario?

      I found this documentation after a quick google, but it may be worth a closer look:
      https://help.sap.com/docs/ABAP_PLATFORM_NEW/468a97775123488ab3345a0c48cadd8f/16d43eb0472c4d5a9439ca1bf92c915d.html

      Regards,

      Peter