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.
@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.
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.
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.
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' }
}
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
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.
@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.
