Recap SAP Fiori Elements important annotations in 2 minutes

In this article, we will quickly recap how to build an app using SAP Fiori Elements. The idea is to re-learn the most important syntax and keywords required to create a SAP Fiori Elements app.

Why use SAP Fiori Elements for app development?

Let’s quickly discuss why to use SAP Fiori Elements for app development. Fiori Elements apps are template-based, so we get a consistent UX design, less development effort, and a future-proof, low-maintenance app. With Fiori Elements, you build enterprise-grade Apps quickly without worrying about complex JavaScript UI.

Use of OData V4 in Fiori Elements app development

OData V4 brings higher efficiency to business applications. Compared to OData V2, its benefits include compressed metadata, enhanced ability to handle complex queries, and support for advanced analytical capabilities.

It is suggested to use OData V4 for sap Fiori Elements development. For this article, we assume that you have created an OData V4 service.

SAP Fiori Elements App on ABAP RESTful Application Programming Model OData Service

The easiest way to learn and test the Fiori Elements syntax is on a RAP OData service. Utilize the freely available ABAP environment of the SAP BTP trial account to generate an ABAP RAP-based OData service. Create an ABAP Cloud project by connecting the ADT with the SAP BTP Trial account. Create a RAP project of your choice and generate an OData service. Make sure you choose the OData V4 version for the OData service. Publish the OData V4 service.

Annotate inside the ABAP CDS Metadata Extension of the Projection View

  • UI Annotations will be added to the Metadata Extension file of the projection view (and not directly within the Projection view)
  • Create an ABAP CDS Metadata Extension for the projection view.

@UI.LineItem to add columns to List Report Table

Your Fiori Elements app will have a list report page and an object page. @UI.lineItem – In the Fiori Elements App, to add columns to the table, annotate the corresponding fields with the ABAP CDS @UI.lineItem annotation.

@Metadata.layer: #CORE

annotate view Ztravel_projection_view

with

{

   @UI.lineItem: [{position: 10}]

   TravelID;

   @UI.lineItem: [{position: 20}]

   AgencyID;

   @UI.lineItem: [{position: 30}]

   CustomerID;

   @UI.lineItem: [{position: 40}]

   BeginDate;

   @UI.lineItem: [{position: 50}]

   EndDate;

   @UI.lineItem: [{position: 60}]

   BookingFee;

   @UI.lineItem: [{position: 70}]

   TotalPrice;

   @UI.lineItem: [{position: 80}]

   OverallStatus;

   @UI.lineItem: [{position: 90}]

   LastChangedAt;

}

This is the result of the above annotation.

image.png

@UI.selectionField to Add Filter Fields to the List Report

@UI.selectionField adds filter option to the list report in the header area. Annotate the required fields to create filter as shown in the code below.

@Metadata.layer: #CORE

annotate view Ztravel_projectionview

with

{

   @UI.lineItem: [{position: 10}]

   @UI.selectionField: [{position: 10}]

   TravelID;

   @UI.lineItem: [{position: 20}]

   @UI.selectionField: [{position: 20}]

   AgencyID;

   @UI.lineItem: [{position: 30}]

   @UI.selectionField: [{position: 30}]

   CustomerID;

   @UI.lineItem: [{position: 40}]

   BeginDate;

   @UI.lineItem: [{position: 50}]

   EndDate;

   @UI.lineItem: [{position: 60}]

   BookingFee;

   @UI.lineItem: [{position: 70}]

   TotalPrice;

   @UI.lineItem: [{position: 80}]

   OverallStatus;

   @UI.lineItem: [{position: 90}]

   LastChangedAt;

}

You get filter options in the header.

image.png

Add Criticality to the Travel Status Column

To add criticality to a column, complete it in 2 steps.

1st in your interface CDS view, create a field based on OVERALL_STATUS as shown below.

case OVERALL_STATUS

  when 'O' then 2

  when 'A' then 3

  when 'X' then 1

  else 0

end   as OverallStatusCriticality,

The above code, based on OVERALL_STATUS value, generates number, 1,2 or 3. This is the criticality number. Based on this integer, the criticality effect will be generated. In our case, we are just utilizing 1, 2 and 3.

  • 0 – Neutral
  • 1 – Negative (red)
  • 2 – Critical (orange)
  • 3 – Positive (green)
  • 5 – New Item (blue): Used to highlight new items which were created outside of the app (for example, through an API in the back-end, or as a side effect), and need the user’s attention

2nd step is to annotate the corresponding field in the Metadata extension file.

@UI.lineItem: [{position: 80, criticality: 'OverallStatusCriticality'}]

   OverallStatus;

 You get this result in the output.

image.png

Display a description text instead of code using annotation @ObjectModel.text.element

If you notice, for the Overall Status column, we are displaying codes like O, A or X and so on. Instead of these codes, we plan to display meaningful text.

The text of these codes is made available in the interface view data definition via association.

Next, annotate the OveallStatus field in the travel interface view data definition  with annotation @ObjectModel.text.element.

@ObjectModel.text.element annotation establishes the conjunction of a field with its descriptive language-independent texts.

_TravelStatus.TravelStatusText as TravelStatusText,

 @ObjectModel.text.element: ['TravelStatusText']

 OverallStatus, 

Next, jump into the metadata extension file and add annotation @UI.textArrangement: #TEXT_ONLY to the OverallStatus field.

@UI.lineItem: [{position: 80, criticality: 'OverallStatusCriticality'}]

   @UI.textArrangement: #TEXT_ONLY

   OverallStatus;   

You see the corresponding text instead of code in the output.

image.png

Annotation for SAP Fiori Elements Object Page

Adding Title and Description to the Header Area of the Object Page using @UI.headerInfo annotation

In the metadata extension file of the Travel projection view, add the @UI.headerInfo annotation at the top of the file.

@Metadata.layer: #CORE

@UI.headerInfo: {

   typeNamePlural: 'Travels',

   typeName: 'Travel',

   title: { type: #STANDARD, value: 'Description' },

   description: { type: #STANDARD, value: 'TravelID' }

}
image.png

Note- the typeNamePlural property defines the title of the table on the list report page.

@UI.dataPoint to Display more fields in the Header area of the Object Page

This will be a 2 step process.

1st annotate the field that you want to place in the Header area of the Object Page with annotation @UI.dataPoint

For example, to display TotalPrice and OverallStatus in the header area of the Object Page, annotate it as shown below.

@UI.lineItem: [{position: 70}]

   @UI.dataPoint: { qualifier: 'PriceData', title: 'Total Price' }

   TotalPrice;

   @UI.lineItem: [{position: 80, criticality: 'OverallStatusCriticality'}]

   @UI.textArrangement: #TEXT_ONLY

   @UI.dataPoint: { qualifier: 'StatusData', title: 'Status', criticality: 'OverallStatusCriticality' }

   OverallStatus;  

2nd step is to Add the @UI.facet annotation and reference the @UI.dataPoint annotation. Give close attention to The targetQualifier which identifies the referenced @UI.dataPoint annotation.

Refer the code snippet below.

annotate view Ztravel_projectionview

with

{

   @UI.facet: [{

       purpose: #HEADER,

       position: 10,

       type: #DATAPOINT_REFERENCE,

       targetQualifier: 'PriceData'

   },

   {

       purpose: #HEADER,

       position: 20,

       type: #DATAPOINT_REFERENCE,

       targetQualifier: 'StatusData'

   }]

   @UI.lineItem: [{position: 10}]

   @UI.selectionField: [{position: 10}]

   TravelID;

And this is how the output will look like

image.png

Add an Identification Section to the Object Page Body

To display information in the body of the Object Page, it will be a 2-step process.

1st Step – Annotate the fields that you want to display on the body of the Object page with @UI.identification annotation. For example, we want to display the AgencyID and CustomerID in the body of the Object Page, and then we will annotate these 2 fields as shown below.

@UI.lineItem: [{position: 20}]

   @UI.selectionField: [{position: 20}]

   @UI.identification: [{position: 10}]

   AgencyID;

   @UI.lineItem: [{position: 30}]

   @UI.selectionField: [{position: 30}]

   @UI.identification: [{position: 20}]

   CustomerID;   

2nd step – You need to create a section in the object page body if you don’t have. This is an empty container, and you can add subsections inside it. The code snippet below creates a General Information section and a General sub-section inside it.

The UI.facet code snippet will now be as shown below.

@UI.facet: [{

       purpose: #HEADER,

       position: 10,

       type: #DATAPOINT_REFERENCE,

       targetQualifier: 'PriceData'

   },

   {

       purpose: #HEADER,

       position: 20,

       type: #DATAPOINT_REFERENCE,

       targetQualifier: 'StatusData'

   },

   {

       label: 'General Information',

       type: #COLLECTION,

       id: 'GeneralInfo',

       position: 10

   },

   {

       label: 'General',

       type: #IDENTIFICATION_REFERENCE,

       parentId: 'GeneralInfo' /* The section id */

   }]   

This is the output post the above changes.

image.png

@UI.fieldGroup to add more subsections to a section in the Object Page Body

1st step – annotate the fields with @UI.fieldGroup. We will annotate the TotalPrice and BookingFee field.

2nd step – Add another record to @UI.facet annotation of type #FIELDGROUP_REFERENCE for the Prices subsection

Similarly, create another sub-section, Dates, and add fields BeginDate and EndDate to it.

The final code looks as shown below.

@Metadata.layer: #CORE

@UI.headerInfo: {

   typeNamePlural: 'Travels',

   typeName: 'Travel',

   title: { type: #STANDARD, value: 'Description' },

   description: { type: #STANDARD, value: 'TravelID' }

}

annotate view Ztravel_projectionview

with

{

   @UI.facet: [{

       purpose: #HEADER,

       position: 10,

       type: #DATAPOINT_REFERENCE,

       targetQualifier: 'PriceData'

   },

   {

       purpose: #HEADER,

       position: 20,

       type: #DATAPOINT_REFERENCE,

       targetQualifier: 'StatusData'

   },

   {

       label: 'General Information',

       type: #COLLECTION,

       id: 'GeneralInfo',

       position: 10

   },

   {

       label: 'General',

       type: #IDENTIFICATION_REFERENCE,

       parentId: 'GeneralInfo' /* The section id */

   },

   {

       label: 'Prices',

       purpose: #STANDARD,

       position: 20,

       type: #FIELDGROUP_REFERENCE,

       parentId: 'GeneralInfo', /* The section id */

       targetQualifier: 'PricesGroup'

   },

   {

       label: 'Dates',

       purpose: #STANDARD,

       position: 30,

       type: #FIELDGROUP_REFERENCE,

       parentId: 'GeneralInfo', /* The section id */

       targetQualifier: 'DatesGroup'

   }]

   @UI.lineItem: [{position: 10}]

   @UI.selectionField: [{position: 10}]

   TravelID;

   @UI.lineItem: [{position: 20}]

   @UI.selectionField: [{position: 20}]

   @UI.identification: [{position: 10}]

   AgencyID;

   @UI.lineItem: [{position: 30}]

   @UI.selectionField: [{position: 30}]

   @UI.identification: [{position: 20}]

   CustomerID;

   @UI.lineItem: [{position: 40}]

   @UI.fieldGroup: [{qualifier: 'DatesGroup', position: 10}]

   BeginDate;

   @UI.lineItem: [{position: 50}]

   @UI.fieldGroup: [{qualifier: 'DatesGroup', position: 20}]

   EndDate;

   @UI.lineItem: [{position: 60}]

   @UI.fieldGroup: [{qualifier: 'PricesGroup', position: 20}]

   BookingFee;

   @UI.lineItem: [{position: 70}]

   @UI.dataPoint: { qualifier: 'PriceData', title: 'Total Price' }

   @UI.fieldGroup: [{qualifier: 'PricesGroup', position: 10}]

   TotalPrice;

   @UI.lineItem: [{position: 80, criticality: 'OverallStatusCriticality'}]

   @UI.textArrangement: #TEXT_ONLY

   @UI.dataPoint: { qualifier: 'StatusData', title: 'Status', criticality: 'OverallStatusCriticality' }

   OverallStatus;

   @UI.lineItem: [{position: 90}]

   LastChangedAt;

}

Below is the output post these changes.

image.png