In the CDS files of your RAP based service you can add annotations to refine the user interface. These CDS annotations will be translated into OData annotations used by SAP Fiori elements to generate the UIs. UI annotations are stored within metadata extension files to separate them from the CDS view structure for better reading.
In this unit you will add annotations to refine a list report (the 'travel list'). You will use the ABAP Development Tools in Eclipse which you installed in the hands-on exercises for week 1 unit 4 .
You will learn how to
- Add columns to the table
- Add selection fields to the filter bar
- Add list report header information
- Define a value help as a drop down list
- Define criticality ratings
Whenever your unique suffix for creating objects is needed, the object names within this tutorial are named with suffix "######". For the screenshots the suffix "000100" was used.
Prerequisite: You have performed all previous exercises of this course.
-
Start the service preview
When the service is published, its entities are shown within a tree-view on the right part of the service binding.
With that the service is actively running and can be used for creating SAP Fiori elements applications.
To immediately see the service running in an application you can start the preview mode within the ABAP Development tools. Simply select the main entity Travel in the tree-view and press the Preview... button on the right side of the service binding.
-
Logon to the service preview
A separate browser window opens and you need to logon with your cloud trial account. Press the Log On button after you have entered your account email and password.
After logging in, a generated list report object page application will be shown in preview mode. Since there are no line item annotations available, no columns are shown in the list report table.
Annotations controlling the UI can be stored in metadata extension files. In this section such a file will be created for the Travel entity and a first annotation will be added.
-
Right clicking the
ZC_FE_TRAVEL_######
projection view for the Travel entity opens a context menu. Choose option New Metadata Extension.Enter the name of your metadata extension file. Choose the same name as your projection view file name
ZC_FE_TRAVEL_######
and enter a description as well. Click Next.A transport request is already assigned to the metadata extension file. Press Finish to confirm the creation of the file.
-
Now open the new metadata extension file
ZC_FE_TRAVEL_######
within the Metadata Extensions folder. To show a first column within the list report table, add the content shown in the coding example below.You can use code completion by pressing
CTRL+SPACE
at the related coding positions, e.g. when adding the@UI.lineItem
annotation, just type@UI
and then pressCTRL+SPACE
to choose the entry from the list of proposals.@Metadata.layer: #CORE annotate view ZC_FE_TRAVEL_###### with { @UI.lineItem: [{ position: 10 }] TravelID; }
Note that the metadata layer of our app is set to
#CORE
. Metadata extensions support a layering concept where#CORE
has the lowest and#CUSTOMER
has the highest priority. Code completion shows you the full list of available values.To finish this step, press Save and Activate to take over the changes in your metadata extensions file.
Check your changes by refreshing the preview of your application and press the Go button to load the data.
You will now see the column Travel ID made visible on the list report table by the
@UI.lineItem
annotation added to the metadata extensions file. The data shown in the column is loaded from the database with the request triggered by the Go button.
To see some more data on the list report you are now adding more columns to the table and to simplify the selection of data you will add filter fields to the filter bar.
-
If no longer open, please open the metadata extension file
ZC_FE_TRAVEL_######
located in folderCore Data Services
>Metadata Extensions
.Now add the fields with the corresponding
lineItem
annotations to the metadata extension file as shown in the code fragment below. The propertyposition
controls the order of the columns within the list report table.@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 }] LocalLastChangedAt;
As a result, after saving and activating the metadata extension file and then refreshing the preview of your application, you will see the additional columns shown in the list report table.
Note: The default table type of a list report is the responsive table. You can show or hide columns of list report and object page tables depending on the screen width using the
Importance: #High/#Medium/#Low
property in the lineItem annotation. If the screen size is narrowed down too much, the columns annotated with High and Medium start to pop in, while the ones annotated with Low are hidden. As soon as the first column is hidden, a buttonShow Details
appears in the table toolbar. -
To assign specific fields to the filter bar you will use the
selectionField
annotation. Add this annotation to the three existing fieldsAgencyID
,CustomerID
andOverallStatus
as shown in the coding example below.@UI.lineItem: [{ position: 20 }] @UI.selectionField: [{ position: 10 }] AgencyID; @UI.lineItem: [{ position: 30 }] @UI.selectionField: [{ position: 20 }] CustomerID;
@UI.lineItem: [{ position: 80 }] @UI.selectionField: [{ position: 30 }] OverallStatus;
Again save and activate the file and refresh the application to see the changes on the UI.
You can now filter the data loaded into the list report by specifying values for these additional selection fields.
Now the list report table shall be sorted by the last updated travel records and also the number of records available in the database shall be visible.
-
To achieve this, add header information to the metadata extension file right above the view annotation. Note that we didn't cover the presentationVariant property in the corresponding openSAP video for timing reasons.
Reminder: You can use code completion by pressing
CTRL+SPACE
at the related coding positions, e.g. when adding the@UI.headerInfo
annotation, just type@UI
and then pressCTRL+SPACE
to choose the entry from the list of proposals.@Metadata.layer: #CORE @UI: { headerInfo: { typeName: 'Travel', typeNamePlural: 'Travels' }, presentationVariant: [{ sortOrder: [{ by: 'LocalLastChangedAt', direction: #DESC }], visualizations: [{ type: #AS_LINEITEM }] }] } annotate view ZC_FE_TRAVEL_###### with { ...
The
@UI.headerInfo
annotation contains information about the naming of the main entity in singular and plural format and it shows the number of records available in the database in the table title. The table title is determined by thetypeNamePlural
property.The
@UI.presentationVariant
annotation controls the sorting of the table by fieldLocalLastChangedAt
viasortOrder
property. Thevisualizations
property determines that the sorting is applied to the list report table. -
Save and activate the metadata extension file and refresh the application preview to see the result on the UI.
Instead of showing IDs for the fields Travel ID, Agency ID and Customer ID one would preferably show descriptions or names. Additionally some labels of specific fields will be changed globally to make the new label accessible wherever the fields will be used on the list report or object page.
-
You will achieve this by using specific annotations which are implemented within the projection view
ZC_FE_TRAVEL_######
. For this, open the projection view located in folder Core Data Services > Data Definitions which contains the root view definitions for the Travel entity. -
Add the
@EndUserText
and@ObjectModel
annotations to the fields as shown in the coding fragments below.Annotation
@EndUserText.label
defines the column label for the related fields.@ObjectModel.text.element
controls the source of the content shown for the related field. For fieldTravelID
this will be theDescription
field from this view.AgencyID
andCustomerID
will get their content from the related field through the corresponding association.@EndUserText.label: 'Travel' @ObjectModel.text.element: [ 'Description' ] TravelID,
@EndUserText.label: 'Agency' @ObjectModel.text.element: ['AgencyName'] AgencyID, _Agency.Name as AgencyName,
@EndUserText.label: 'Customer' @ObjectModel.text.element: ['LastName'] CustomerID, _Customer.LastName as LastName,
@EndUserText.label: 'Status' OverallStatus,
@EndUserText.label: 'Last Changed At' LocalLastChangedAt,
The semantic key for the view is
TravelID
and was automatically added by the generator. The content of the field will be highlighted (bold) with the ID underneath, and the draft indicator will be shown in case a draft exists for the respective item. You can find it in your ZC_FE_TRAVEL_###### view:... @Search.searchable: true @ObjectModel.semanticKey: ['TravelID'] define root view entity ZC_FE_TRAVEL_###### ...
Note: In the screenshot below the ID underneath the bold description in TravelID is missing. This is due to a temporary issue we had in the Preview during the time of recording.
After saving and activating the file and refreshing the application you will see the changed labels and content for the fields Travel, Agency, Customer, Status and Last Changed At.
When you click the value help icon of the selection field Customer in the filter bar, you get a dialog which provides the option to conditionally load data by the customer id. For better usability you would rather select customer data like name or address from a list.
-
To implement the value help, assign the annotation
@Consumption.valueHelpDefinition
to the fieldCustomerID
within the projection viewZC_FE_TRAVEL_######
.@EndUserText.label: 'Customer' @ObjectModel.text.element: ['LastName'] @Consumption.valueHelpDefinition: [{ entity : {name: '/DMO/I_Customer', element: 'CustomerID' } }] CustomerID, _Customer.LastName as LastName,
The entity property
name
points to the data view andelement
contains the key for the selection. -
After saving, activating and refreshing your application, the field Customer provides the improved value help that allows a user friendly selection of customer data within the Search and Select tab. You are still able to do a conditional selection by choosing the Define Conditions tab on the dialog. By entering search values such as the Last Name and pressing the Go button, the resulting list is shown in the table. Selecting specific lines in the table and pressing the OK button will load a selected list of Travel items into list report.
Selection field Status also shows a conditional value help by default. From a user perspective it would be nice to get a list of values presented as a drop-down list since the number of different values is very limited.
-
In the projection view for the Travel entity
ZC_FE_TRAVEL_######
the annotation for the value help has to be defined for theOverallStatus
field. As with the fieldCustomerID
(see above), the annotation@Consumption.valueHelpDefinition
is used with propertiesname
andelement
containing the appropriate values.... @EndUserText.label: 'Status' @Consumption.valueHelpDefinition: [{ entity : {name: 'ZI_FE_STAT_######', element: 'TravelStatusId' } }] OverallStatus, ...
Save and activate the view.
-
Open the CDS view for the status description
ZI_FE_STAT_######
. Just above the view definition, insert an@ObjectModel.resultSet.sizeCategory
annotation with value#XS
. This results in a drop-down list.... @EndUserText.label: 'Travel Status view entity' @ObjectModel.resultSet.sizeCategory: #XS -- drop down menu for value help define view ZI_FE_STAT_###### ...
Save and activate the view.
-
After refreshing the application the Status field is now a drop-down list. Select one or more of the available status codes and press the Go button to load the filtered list.
The column Status currently shows the internal codes stored within OverallStatus
, but instead the description for these codes shall be displayed.
Although the related association is set correctly for ZI_FE_TRAVEL_######
and descriptions are available through ZI_FE_STAT_######
, the corresponding text annotation for the projection view is missing.
-
You can check the association already available within the CDS view for the travel entity
ZI_FE_TRAVEL_######
in folder Data Definitions and the publication of this association to make it available for projection views (lines 6 & 14 in the code snippet below).define root view entity ZI_FE_TRAVEL_###### as select from ZFE_ATRAV_###### association [0..1] to /DMO/I_Agency as _Agency on $projection.AgencyID = _Agency.AgencyID association [0..1] to I_Currency as _Currency on $projection.CurrencyCode = _Currency.Currency association [0..1] to /DMO/I_Customer as _Customer on $projection.CustomerID = _Customer.CustomerID association [0..1] to ZI_FE_STAT_###### as _TravelStatus on $projection.OverallStatus = _TravelStatus.TravelStatusId composition [0..*] of ZI_FE_Booking_###### as _Booking { key TRAVEL_UUID as TravelUUID, ... ... _Customer, _TravelStatus }
-
Now the access to the status description has to be set within the projection view
ZC_FE_TRAVEL_######
. Add the text annotation@ObjectModel.text.element
for fieldOverallStatus
as shown below (line 2). To load the description the corresponding field from the status description view has to be accessed by the association_TravelStatus
(line 5).@EndUserText.label: 'Status' @ObjectModel.text.element: ['TravelStatusText'] @Consumption.valueHelpDefinition: [{ entity : {name: 'ZI_FE_STAT_######', element: 'TravelStatusId' } }] OverallStatus, _TravelStatus.TravelStatusText as TravelStatusText,
Save and activate the view.
-
With these settings the description is displayed in the column Status but additionally, the code is shown within parentheses. You can use the
@UI.textArrangement
annotation with value#TEXT_ONLY
to omit the key. Open the metadata extension fileZC_FE_TRAVEL_######
and add the text arrangement annotation to the fieldOverallStatus
(line 3).@UI.lineItem: [{ position: 80 }] @UI.selectionField: [{ position: 30 }] @UI.textArrangement: #TEXT_ONLY OverallStatus;
Save and activate the metadata extension.
-
After refreshing your application you will see the status description within the Status column.
This step requires implementing some additional backend logic. You can complete the remaining exercises in this course also if you skip this step. In this case you will not get the semantic coloring for the status field. Neither in the list report (travel list) nor in the object page (travel details).
The values of the Status field can be semantically colored to visually differentiate the meaning. This can be achieved by using the criticality property for the lineItem annotation.
-
The criticality feature requires specific values for the different colors to be shown on the UI. Therefore a new field
OverallStatusCriticality
will be defined in the CDS viewZI_FE_TRAVEL_######
. This field will be filled with color codes derived from the values of the fieldoverall_status
. See below coding fragment which shows a case-structure to define the content of the new fieldOverallStatusCriticality
within lines 5 to 10.... description as Description, overall_status as OverallStatus, case overall_status when 'O' then 2 -- 'open' | 2: yellow colour when 'A' then 3 -- 'accepted' | 3: green colour when 'X' then 1 -- 'rejected' | 1: red colour else 0 -- 'nothing' | 0: unknown end as OverallStatusCriticality, @Semantics.user.createdBy: true created_by as CreatedBy, ...
Take over the case-structure into the CDS view
ZI_FE_TRAVEL_######
just below the fieldoverall_status
. Save and activate the view. -
Adding a new field to the CDS view is a structural change which requires a recreation of the corresponding draft table
ZFE_DTRAV_######
. This draft table contains all the fields of the CDS view.This can easily be done by applying a quick fix within the behavior definition file
ZI_FE_TRAVEL_######
in folder Core Data Services > Behavior Definitions. Open this file in your editor and you will immediately see the error shown in the line where the draft table for the Travel entity is referenced.Click on the light bulb icon on the left in that line or position your cursor on the draft table file name
ZFE_DTRAV_######
and pressCTRL + 1
. The system proposes to recreate the draft table. By double-clicking on the proposal, the recreation of the table will be started.As soon as the recreation is finished, you will see the draft table
ZFE_DTRAV_######
loaded into the editor containing the new fieldOverallStatusCriticality
.Save and activate the draft table and then activate also the behavior definition file
ZI_FE_TRAVEL_######
which is still open in your editor. The error disappears as soon as the behavior definition is activated. If ADT still shows the error, close the behavior definition and open it again. -
To be able to use the new field within UI annotations you need to take it over to the projection view of the travel entity
ZC_FE_TRAVEL_######
. Insert the fieldOverallStatusCriticality
just below the definition for the fieldOverallStatus
(see line 7 in the coding fragment).... @ObjectModel.text.element: ['TravelStatusText'] @Consumption.valueHelpDefinition: [{ entity : {name: 'ZI_FE_STAT_######', element: 'TravelStatusId' } }] OverallStatus, _TravelStatus.TravelStatusText as TravelStatusText, OverallStatusCriticality, CreatedBy, ...
Save and activate the projection view.
-
As a last step you need to add the criticality to the metadata extension for the Travel entity
ZC_FE_TRAVEL_######
.This can be done by adding the property
criticality
with valueOverallStatusCriticality
to the@UI.lineItem
annotation of fieldOverallStatus
(see line 5 in the coding fragment).... @UI.lineItem: [{ position: 70 }] TotalPrice; @UI.lineItem: [{ position: 80, criticality: 'OverallStatusCriticality' }] @UI.selectionField: [{ position: 30 }] @UI.textArrangement: #TEXT_ONLY OverallStatus; @UI.lineItem: [{ position: 90 }] LocalLastChangedAt; ...
Save and activate the metadata extension file.
Refresh your application and reload the data by pressing Go in the list report. Now the content of column Status is shown in different colors depending on the values of the field.
You have completed the exercise! In this unit, you have learned how to create a list report using ABAP CDS annotation.