This is a test message to test the length of the message box.
Login
|
Tools My IDE Actions
Created by Software-Heroes

ADT - Metadata Wizard [MIA]

605

In this article, we'll take a look at the Metadata Wizard and how it might simplify your life when creating UI annotations in RAP in the future.

Advertising


In this article, we'll walk through the concept of the "Metadata Wizard," how it currently works, and how it might help you in the future.

 

Introduction

In the last article, we created a RAP object using a template, saving a lot of time when creating objects. However, we weren't entirely satisfied with the UI, as too much information was displayed and there was no clear structure. In this article, we'll revise the Metadata Extension, but not manually. Instead, we'll use a prototype wizard that we've implemented as an IDE Action.

 

Idea

In the Metadata Extension, we define our UI annotations to create the Fiori Elements UI, define the elements, and position them. In most cases, we initially follow the same pattern to design the ListReport and the subsequent Object Page. The generators usually define an initial view, which we almost always need to revise.This is where the Metadata Wizard comes into play, giving us a quick start to the editing process and allowing us to easily place, hide, and group elements.

 

IDE Action

In this section, we'll take a look at the construction of the IDE Action, the ideas we pursued, and what the final result looks like.

 

Information

What information do we actually need when creating the annotations for the fields? In most cases, we start with the different facades and then assign the fields to them. Let's start with an input for our IDE Action. In the simplest case, we have one area for the different facets and one area for the fields. Since we want to maintain different information here, we'll create two tables. You can find out how to create and design an IDE Action by searching for IDE Actions.

TYPES:
  BEGIN OF facet,
    "! <p class="shorttext">ID</p>
    id               TYPE string,
    "! <p class="shorttext">Parent ID</p>
    parent_id        TYPE string,
    "! <p class="shorttext">Label</p>
    label            TYPE string,
    "! <p class="shorttext">Type</p>
    type             TYPE facet_type,
    "! <p class="shorttext">Position</p>
    position         TYPE string,
    "! <p class="shorttext">Qualifier</p>
    target_qualifier TYPE string,
    "! <p class="shorttext">Reference</p>
    target_element   TYPE string,
    "! <p class="shorttext">Field to Hide</p>
    hide_facet       TYPE string,
    old              TYPE string,
  END OF facet.
TYPES facets TYPE STANDARD TABLE OF facet WITH EMPTY KEY.

TYPES:
  BEGIN OF field,
    "! <p class="shorttext">Field</p>
    name               TYPE string,
    "! <p class="shorttext">New Label</p>
    label              TYPE string,
    "! <p class="shorttext">Selection [P]</p>
    pos_selection      TYPE string,
    "! <p class="shorttext">LineItem [P]</p>
    pos_lineitem       TYPE string,
    "! <p class="shorttext">Identification [P]</p>
    pos_identification TYPE string,
    "! <p class="shorttext">FieldGroup [P]</p>
    pos_fieldgroup     TYPE string,
    "! <p class="shorttext">Qualifier</p>
    qualifier          TYPE string,
    "! <p class="shorttext">Field to Hide</p>
    hide_field         TYPE string,
  END OF field.
TYPES fields TYPE STANDARD TABLE OF field WITH EMPTY KEY.

 

Now that we have defined the first structures, you will already be able to see from the fields which features we support. We can hide fields and areas via fields, create different areas, or assign our own labels. If we start the IDE action, we will already find all the elements on the input.

 

Using the "Hide" button, we will later make fields disappear completely from the UI, for example, if they are UUID key fields, without implementing much logic.

 

Defaults

In the next step, we want to pre-populate the default values. Let's begin with the different faces in the view. Using the XCO library, we check if the Core Data Service exists in the system, using the name of the Metadata Extension, which might differ from the Core Data Service name. Then, we almost always need a general facet to which we assign all fields, similar to the generator standard. Next, we create a facet for each composition in the Core Data Service to include the entities as a table. We can assign the fields directly to the general facet and simply increment the position in steps of 10. We can then pass the result to the IDE action as the default.

If we now run the IDE action again, we get the corresponding pre-population. In this case, we use the metadata extension of the entity ZBS_C_SASale from our sales app.

 

Customization

The IDE actions are not just meant to be "dumb" forms that you can fill in at the end, but also to support you in your work. For example, if you change the qualifier of the facet, then all fields with that facet should also change, otherwise we will no longer have a mapping or, in the worst case, we will have to make the adjustment for each field ourselves.

 

If we want to hide fields on the UI, we use an action in the table. Here we only need to select the field and execute the action; then the properties will be deleted and the field will later be set to "hidden".

 

Features

Currently, the IDE action primarily supports you in creating UI annotations. More complex features such as headers, buttons, and other annotations are still missing. Therefore, the action is intended for a quick start, and further customization must be done by you as the developer. An open point is the analysis of existing UI annotations so that the wizard could also be used for customizations. We would load the source code and pre-populate the form. This would also entail supporting more features.

 

Generation

Now that the prototype of the IDE action is complete, we'll take care of the metadata of our Sales App from the last article and update the UI with our new action.

 

Sales

The metadata extension ZBS_C_SASale contains the List Report, the actual object page, and some entities below it. Therefore, the object page should be a bit cleaner. As a first step, we therefore go to the Metadata Extension and delete all existing information except for the header annotations. We then start the action with CTRL + ALT + R and can begin the configuration.

 

After the action has been executed, we receive the code comparison and can check the generated changes. In this case, we'll use the result.

 

Looking at the UI annotations, the different facets have been generated and the fields with their corresponding boundaries have been used. The generated code from the configuration can be found in the example.

@Metadata.layer: #CORE
@UI.headerInfo.title.type: #STANDARD
@UI.headerInfo.title.value: 'PartnerNumber'
@UI.headerInfo.description.type: #STANDARD
@UI.headerInfo.description.value: 'SalesDate'
annotate view ZBS_C_SASALE with
{
  @UI.facet: [
    {
      id: 'idGeneral',
      label: 'General Information',
      position: 10 ,
      type: #IDENTIFICATION_REFERENCE,
      targetQualifier: 'GENERAL'
    },
    {
      id: 'idDifference',
      label: 'Difference',
      position: 20,
      type: #IDENTIFICATION_REFERENCE,
      targetQualifier: 'DIFF'
    },
    {
      id: 'idInformation',
      label: 'Information',
      position: 30,
      type: #IDENTIFICATION_REFERENCE,
      targetQualifier: 'INFO'
    },
    {
      id: 'idAdmin',
      label: 'Admin Fields',
      position: 40,
      type: #IDENTIFICATION_REFERENCE,
      targetQualifier: 'ADMIN'
    },
    {
      id: 'idSASeller',
      label: 'Seller',
      position: 50,
      type: #LINEITEM_REFERENCE,
      targetElement: '_SASeller'
    },
    {
      id: 'idSASold',
      label: 'Sold',
      position: 60,
      type: #LINEITEM_REFERENCE,
      targetElement: '_SASold'
    },
    {
      id: 'idSAInfo',
      label: 'Info',
      position: 70,
      type: #LINEITEM_REFERENCE,
      targetElement: '_SAInfo'
    }
  ]

  @UI.hidden: true
  UUID;

  @UI.selectionField: [ { position: 10 } ]
  @UI.lineItem: [ { position: 20  } ]
  @UI.identification: [ { position: 20 , qualifier: 'GENERAL' } ]
  @EndUserText.label: 'Partner'
  PartnerNumber;

  @UI.selectionField: [ { position: 20 } ]
  @UI.lineItem: [ { position: 30  } ]
  @UI.identification: [ { position: 30 , qualifier: 'GENERAL' } ]
  @EndUserText.label: 'Sales Date'
  SalesDate;

  @UI.lineItem: [ { position: 40  } ]
  @UI.identification: [ { position: 40 , qualifier: 'GENERAL' } ]
  @EndUserText.label: 'Sales Volume'
  SalesVolume;

  @UI.selectionField: [ { position: 30 } ]
  @UI.lineItem: [ { position: 50  } ]
  @UI.identification: [ { position: 50 , qualifier: 'GENERAL' } ]
  @EndUserText.label: 'Sales Currency'
  SalesCurrency;

  @UI.identification: [ { position: 60 , qualifier: 'DIFF' } ]
  @EndUserText.label: 'Difference Amount'
  DifferenceAmount;

  @UI.identification: [ { position: 70 , qualifier: 'DIFF' } ]
  @EndUserText.label: 'Currency'
  DifferenceCurrency;

  @UI.identification: [ { position: 80 , qualifier: 'DIFF' } ]
  @EndUserText.label: 'Difference Quantity'
  DifferenceQuantity;

  @UI.identification: [ { position: 90 , qualifier: 'DIFF' } ]
  @EndUserText.label: 'Unit'
  DifferenceUnit;

  @UI.identification: [ { position: 100 , qualifier: 'INFO' } ]
  @EndUserText.label: 'Comment'
  SaleComment;

  @UI.identification: [ { position: 110 , qualifier: 'ADMIN' } ]
  @EndUserText.label: 'Created By'
  LocalCreatedBy;

  @UI.identification: [ { position: 120 , qualifier: 'ADMIN' } ]
  @EndUserText.label: 'Created At'
  LocalCreatedAt;

  @UI.identification: [ { position: 130 , qualifier: 'ADMIN' } ]
  @EndUserText.label: 'Local Changed By'
  LocalLastChangedBy;

  @UI.identification: [ { position: 140 , qualifier: 'ADMIN' } ]
  @EndUserText.label: 'Local Changed At'
  LocalLastChangedAt;

  @UI.identification: [ { position: 150 , qualifier: 'ADMIN' } ]
  @EndUserText.label: 'Last Changed At'
  LastChangedAt;
}

 

You can also add labels to the fields via the IDE Actions so that we have clean and translatable text for the UI.

 

Subentities

For the subentities, we only generate the annotations for the ListItem, since we want a clean table in our entity, but don't need the Object Page at the moment. We can hide the technical keys like UUID or Parent ID. You can find the complete resources in the GitHub repository, which is linked below.

 

Header

Currently, if you navigate to the app's object page, you'll see some rather unpleasant text in the header. This text is not currently derived from the UI annotations.

 

For this, we need to take a closer look at the Core Data Service. At the header level, we find the annotation "EndUserText.label", which was defined for the Core Data Service. This will then be used after navigation in the app. We can now adjust this accordingly.

@Metadata.allowExtensions: true
@Metadata.ignorePropagatedAnnotations: true
@EndUserText: {
  label: '###GENERATED Core Data Service Entity'
}
@AccessControl.authorizationCheck: #MANDATORY
define view entity ZBS_C_SASale

 

Complete Example

You can find the IDE action linked below if you want to use it on your own system. We updated the UI annotations with this Commit in the repository for our RAP Examples. We will build on this in the following examples.

 

Conclusion

IDE Actions can make our lives easier and bring a bit more speed to the daily routine of RAP development. Today's IDE Action allows for a quick start to UI design, either directly after running the RAP Generator or after manually creating the objects.

 

Further information:
GitHub - My IDE Actions


Included topics:
ToolsADTEclipseMIAMetadataREX7
Comments (0)



And further ...

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


030: Software-Heroes - My Community

Category - YouTube

Do you want to stay up-to-date with the latest ABAP and SAP knowledge without having to search through every blog individually? My Community brings all community content into a mini-app that you can customize to your liking, so you never miss any news.

12/22/2025

ABAP Tools - IDE Actions (Table)

Category - ABAP

How do you actually create a table and edit it in the IDE Action? Let's look at the input options and how you can ultimately work with the data.

12/09/2025

ABAP Tools - IDE Actions (Side Effects)

Category - ABAP

How can we automatically update information on the UI when something happens with the IDE action? Let's take a closer look at the side effects.

11/18/2025

ABAP Tools - IDE Actions (Value Help)

Category - ABAP

Let's take a detailed look at how we can create a value help for our input for our IDE action in ADT. We'll examine several possibilities and dependencies.

11/11/2025

ABAP Tools - IDE Actions (Input)

Category - ABAP

How can we retrieve information before the actual IDE action is executed in ABAP? Let's implement the first version of a simple input.

11/04/2025