Technical Articles
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
- Example2: Adding Value Help to SmartFilterBar control
- Example3: Add Value Help as a Dropdown List to SmartFilterBar control
- Example4: Display Text value instead of ID in Dropdown List
- Appendix1: Annotations
- Appendix2: Adding annotations to metadata
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
- OData 4.0 Vocabularies – Can be used with OData Version 2.0 service model
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
@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
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
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
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
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
You just need to add this property to the XML
<smartFilterBar:ControlConfiguration displayBehaviour="descriptionAndId" .../>
displayBehaviour
Best Regards,
JJ
Extremely useful!! thanks you very much Péter!
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!
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
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
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
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
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.
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