This is a test message to test the length of the message box.
Login
ABAP RAP UI Annotations
Created by Software-Heroes

RAP - UI Annotations

5075

Today we look at how we can enrich the Fiori Elements with standard elements in order to get a finished app straight away.

We will write again about UI annotations in a separate large article about the diverse elements and possibilities. In this first part, we mainly want to enrich the example from last week with standard elements so that the finished app can be seen as soon as the application is loaded.

 

Annotation

We already wrote about annotations in CDS views in the Core Data Services basics blog. With these additional properties, you can equip fields with additional functions and behavior. Likewise, we want to get additional behavior and a UI for our core data service. To do this, we can equip the fields with annotations from the UI family.

 

Selection

If certain fields are to be filtered from the outset, we can define this directly using the "UI.selectionField" annotation. The fields are displayed as search fields, but can subsequently be expanded or hidden using the standard functionality.

define root view entity ZBS_I_RAPPartner
  as select from zbs_dmo_partner
{
      @UI.selectionField : [ { position: 10 } ]
  key partner          as PartnerNumber,
      @UI.selectionField : [ { position: 20 } ]
      name             as PartnerName,
      street           as Street,
      city             as City,
      country          as Country,
      payment_currency as PaymentCurrency
}

 

The number of the position can be freely selected, but may only be assigned once within the view. It determines the order in which items are displayed, so items are initially numbered in increments of 10 to allow for items to be inserted in between. The result now looks like this:

 

List

Next, we would like to render certain items in the list that will be printed after loading. We achieve this with the annotation "UI.lineItem" which works in a similar way to the selection. We can specify a specific order in which the items will be inserted into the list. With the "importance" attribute, however, we can also determine what information is displayed if not all elements fit on the screen.

define root view entity ZBS_I_RAPPartner
  as select from zbs_dmo_partner
{
      @UI.selectionField : [ { position: 10 } ]
      @UI.lineItem: [{ position: 20, importance: #MEDIUM }]
  key partner          as PartnerNumber,
      @UI.selectionField : [ { position: 20 } ]
      @UI.lineItem: [{ position: 10, importance: #MEDIUM }]
      name             as PartnerName,
      @UI.lineItem: [{ position: 40, importance: #MEDIUM }]
      street           as Street,
      @UI.lineItem: [{ position: 30, importance: #MEDIUM }]
      city             as City,
      @UI.lineItem: [{ position: 50, importance: #HIGH }]
      country          as Country,
      payment_currency as PaymentCurrency
}

 

The Country column is visible in the list because the item is shown with a very high priority. If all elements have the same priority, then they are built up one after the other until no more space is available.

 

Texts

So far, the columns still lack proper headings. You can achieve this by using proper data elements from which the texts can be derived. In our case there are only built-in data types, but we want to display proper texts in the UI. For this, the text can be adjusted with "EndUserText", there are also the elements "label" for the text of the column and "quickinfo", this text is displayed when you move the mouse over the heading.

 

The list now looks much tidier and offers the user explanations when interpreting the output list.

define root view entity ZBS_I_RAPPartner
  as select from zbs_dmo_partner
{
      @UI.selectionField : [ { position: 10 } ]
      @UI.lineItem: [{ position: 20, importance: #MEDIUM }]
      @EndUserText.label: 'Partner'
      @EndUserText.quickInfo: 'Identifier of the partner'
  key partner          as PartnerNumber,
      @UI.selectionField : [ { position: 20 } ]
      @UI.lineItem: [{ position: 10, importance: #MEDIUM }]
      @EndUserText.label: 'Name'
      @EndUserText.quickInfo: 'Partner name'
      name             as PartnerName,
      @UI.lineItem: [{ position: 40, importance: #MEDIUM }]
      @EndUserText.label: 'Street'
      @EndUserText.quickInfo: 'Street and Housenumber'
      street           as Street,
      @UI.lineItem: [{ position: 30, importance: #MEDIUM }]
      @EndUserText.label: 'City'
      @EndUserText.quickInfo: 'City of the partner'
      city             as City,
      @UI.lineItem: [{ position: 50, importance: #HIGH }]
      @EndUserText.label: 'Ctry'
      @EndUserText.quickInfo: 'Country'
      country          as Country,
      @EndUserText.label: 'PayCurr'
      @EndUserText.quickInfo: 'Payment currency'
      payment_currency as PaymentCurrency
}

 

Detail page

If you currently click on a data record in the list, you will automatically be taken to the application's detail screen, but this is still empty. We currently have no information stored for this image. As above, we store a new annotation "UI.identification" in the field. However, this still does not show anything on the detail screen, but we have to assign the fields to a type of group.

To do this, we define a facet at the beginning of the view. This object divides the image into different areas and so we can assign elements or fields. Facets have an ID and must be unique on the image, otherwise no elements will appear on the image.

 

One group

When designing the image, we now have a free choice of how the image should be designed. Let's start with a simple variant and pack everything under one category.

@UI.facet      : [
  {
    id         : 'FacetPartnerFields',
    label      : 'Partner Informations',
    type       : #IDENTIFICATION_REFERENCE,
    targetQualifier: 'PARTNER_INFO'
  }
]

 

Inside the facet we define an area of type "IDENTIFICATION_REFERENCE" under which all objects fall, we set a corresponding ID and a label to be displayed. The "targetQualifier" is used to be able to assign the corresponding fields to the element. This is done via the corresponding annotation:

@UI.selectionField : [ { position: 20 } ]
@UI.lineItem: [{ position: 10, importance: #MEDIUM }]
@UI.identification: [{ position: 20, qualifier: 'PARTNER_INFO' }]
@EndUserText.label: 'Name'
@EndUserText.quickInfo: 'Partner name'
name             as PartnerName,

 

In the end, the detail page looks like this:

 

Two tabs

The next variant creates two "tabs" on the image. The tabs can also be used to navigate later on the detail screen if there are many fields in order to get to the appropriate section. We add a second entry to the facet with a new ID and new assignment for the fields:

@UI.facet      : [
  {
    id         : 'FacetPartnerFields',
    label      : 'Information',
    type       : #IDENTIFICATION_REFERENCE,
    targetQualifier: 'PARTNER_INFO'
  },
  {
    id         : 'FacetPartnerAddress',
    label      : 'Address',
    type       : #IDENTIFICATION_REFERENCE,
    targetQualifier: 'PARTNER_ADDRESS'
  }
]

 

As in the last section, the fields can now be assigned to the corresponding facet and now receive the following detail page (the tabs at the top are clearly visible):

 

Collection

The third and final form of the page is the "Collection", a summary of various references under one category. To do this, we define another facet with the corresponding type and also assign a label, since this is displayed as a new tab. The other two facets are now given a "parentId" to ensure assignment to the collection.

@UI.facet      : [
  {
    id         : 'FacetCollection',
    type       : #COLLECTION,
    label      : 'Partner Collection'
  },
  {
    id         : 'FacetPartnerFields',
    parentId   : 'FacetCollection',
    label      : 'Information',
    type       : #IDENTIFICATION_REFERENCE,
    targetQualifier: 'PARTNER_INFO'
  },
  {
    id         : 'FacetPartnerAddress',
    parentId   : 'FacetCollection',
    label      : 'Address',
    type       : #IDENTIFICATION_REFERENCE,
    targetQualifier: 'PARTNER_ADDRESS'
  }
]

 

The corresponding fields can be assigned again and you will receive the final image. The two facets are combined in one area and given a title, the objects are grouped into areas.

 

Here is the entire Core Data Service again with all the annotations for the last example. As you can see, the amount of coding has increased significantly.

@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'RAP interface for Partner'
define root view entity ZBS_I_RAPPartner
  as select from zbs_dmo_partner
{
      @UI.facet      : [
        {
          id         : 'FacetCollection',
          type       : #COLLECTION,
          label      : 'Partner Collection'
        },
        {
          id         : 'FacetPartnerFields',
          parentId   : 'FacetCollection',
          label      : 'Information',
          type       : #IDENTIFICATION_REFERENCE,
          targetQualifier: 'PARTNER_INFO'
        },
        {
          id         : 'FacetPartnerAddress',
          parentId   : 'FacetCollection',
          label      : 'Address',
          type       : #IDENTIFICATION_REFERENCE,
          targetQualifier: 'PARTNER_ADDRESS'
        }
      ]

      @UI.selectionField : [ { position: 10 } ]
      @UI.lineItem: [{ position: 20, importance: #MEDIUM }]
      @UI.identification: [{ position: 10, qualifier: 'PARTNER_INFO' }]
      @EndUserText.label: 'Partner'
      @EndUserText.quickInfo: 'Identifier of the partner'
  key partner          as PartnerNumber,
      @UI.selectionField : [ { position: 20 } ]
      @UI.lineItem: [{ position: 10, importance: #MEDIUM }]
      @UI.identification: [{ position: 20, qualifier: 'PARTNER_INFO' }]
      @EndUserText.label: 'Name'
      @EndUserText.quickInfo: 'Partner name'
      name             as PartnerName,
      @UI.lineItem: [{ position: 40, importance: #MEDIUM }]
      @UI.identification: [{ position: 30, qualifier: 'PARTNER_ADDRESS' }]
      @EndUserText.label: 'Street'
      @EndUserText.quickInfo: 'Street and Housenumber'
      street           as Street,
      @UI.lineItem: [{ position: 30, importance: #MEDIUM }]
      @UI.identification: [{ position: 40, qualifier: 'PARTNER_ADDRESS' }]
      @EndUserText.label: 'City'
      @EndUserText.quickInfo: 'City of the partner'
      city             as City,
      @UI.lineItem: [{ position: 50, importance: #HIGH }]
      @UI.identification: [{ position: 50, qualifier: 'PARTNER_ADDRESS' }]
      @EndUserText.label: 'Ctry'
      @EndUserText.quickInfo: 'Country'
      country          as Country,
      @UI.identification: [{ position: 60, qualifier: 'PARTNER_INFO' }]
      @EndUserText.label: 'PayCurr'
      @EndUserText.quickInfo: 'Payment currency'
      payment_currency as PaymentCurrency
}

 

Metadata Extension

The UI annotations can grow over time and cause confusion in the actual view. For this we can create a metadata extension to transfer all necessary UI annotations into a separate object. For this you have to create an annotation in the view to be extended:

@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'RAP interface for Partner'
@Metadata.allowExtensions: true
define root view entity ZBS_I_RAPPartner
  as select from zbs_dmo_partner
{

  key partner          as PartnerNumber,
      name             as PartnerName,
      street           as Street,
      city             as City,
      country          as Country,
      payment_currency as PaymentCurrency
}

 

"@Metadata.allowExtensions" announces that the view can be extended with extensions. You can then right-click on the CDS view in the Project Explorer to create the "Metadata Extension" and move the annotations to the new file.

 

After moving, the extension looks like this, but you should note that in contrast to the interface view, some things have changed. The fields are now terminated with a semicolon and only the field name is required (without keywords like "key").

@Metadata.layer: #CUSTOMER
annotate view ZBS_I_RAPPartner with
{
  @UI.facet      : [
    {
      id         : 'FacetCollection',
      type       : #COLLECTION,
      label      : 'Partner Collection'
    },
    {
      id         : 'FacetPartnerFields',
      parentId   : 'FacetCollection',
      label      : 'Information',
      type       : #IDENTIFICATION_REFERENCE,
      targetQualifier: 'PARTNER_INFO'
    },
    {
      id         : 'FacetPartnerAddress',
      parentId   : 'FacetCollection',
      label      : 'Address',
      type       : #IDENTIFICATION_REFERENCE,
      targetQualifier: 'PARTNER_ADDRESS'
    }
  ]

  @UI.selectionField : [ { position: 10 } ]
  @UI.lineItem: [{ position: 20, importance: #MEDIUM }]
  @UI.identification: [{ position: 10, qualifier: 'PARTNER_INFO' }]
  @EndUserText.label: 'Partner'
  @EndUserText.quickInfo: 'Identifier of the partner'
  PartnerNumber;
  @UI.selectionField : [ { position: 20 } ]
  @UI.lineItem: [{ position: 10, importance: #MEDIUM }]
  @UI.identification: [{ position: 20, qualifier: 'PARTNER_INFO' }]
  @EndUserText.label: 'Name'
  @EndUserText.quickInfo: 'Partner name'
  PartnerName;
  @UI.lineItem: [{ position: 40, importance: #MEDIUM }]
  @UI.identification: [{ position: 30, qualifier: 'PARTNER_ADDRESS' }]
  @EndUserText.label: 'Street'
  @EndUserText.quickInfo: 'Street and Housenumber'
  Street;
  @UI.lineItem: [{ position: 30, importance: #MEDIUM }]
  @UI.identification: [{ position: 40, qualifier: 'PARTNER_ADDRESS' }]
  @EndUserText.label: 'City'
  @EndUserText.quickInfo: 'City of the partner'
  City;
  @UI.lineItem: [{ position: 50, importance: #HIGH }]
  @UI.identification: [{ position: 50, qualifier: 'PARTNER_ADDRESS' }]
  @EndUserText.label: 'Ctry'
  @EndUserText.quickInfo: 'Country'
  Country;
  @UI.identification: [{ position: 60, qualifier: 'PARTNER_INFO' }]
  @EndUserText.label: 'PayCurr'
  @EndUserText.quickInfo: 'Payment currency'
  PaymentCurrency;
}

 

Conclusion

In this article we have enriched our Fiori Elements with fields and sections, creating a real application to start working with right away. We went into the various design options and how you can get the detailed image more effectively. You can find the current source code again on GitHub.


Included topics:
RAPBTPUI Annotation
Comments (0)



And further ...

Are you satisfied with the content of the article? We post new content in the ABAP area every Friday and irregularly in all other areas. Take a look at our tools and apps, we provide them free of charge.


RAP - Deep Action in OData v4

Category - ABAP

In this article we will look at actions with deep structures, how we can create them and pass data to an API endpoint.

05/24/2024

BTP - Connect On-Premise (Consumption Model v2)

Category - ABAP

In this article we want to provide another update on the connection of on-premise systems and how this is done with a communication arrangement.

12/15/2023

RAP - Show app count (Tile)

Category - ABAP

This example is about displaying a counter on the tile of a Fiori Elements application and how such a thing can be implemented.

10/06/2023

RAP - Generator (Fiori)

Category - ABAP

In this article we will look at the more complex RAP generator as a Fiori Elements application and what advantages you have with it.

09/15/2023

RAP - Generator (ADT)

Category - ABAP

Today, let's take a look at the RAP Generator, which is already integrated into ABAP Development Tools, and how you can use it to easily build new RAP apps.

09/08/2023