CDS Annotations
RAP / CDS / ODataintermediate

CDS Annotations Part 3: Fiori UI Annotations — Line Items, Facets and Selection Fields

Key takeaway

Build a complete Fiori Elements list report and object page with UI annotations: header info, line items, selection fields, identification, facets, field groups, actions and value helps.

Explanation

📌 KEY POINTS
✅ @UI.lineItem = list columns; @UI.selectionField = filter bar; @UI.headerInfo = object title.

✅ Object page = @UI.facet (sections) pointing to @UI.identification or @UI.fieldGroup.

✅ Actions become buttons via @UI.lineItem / @UI.identification with type #FOR_ACTION.

💡 Value helps: @Consumption.valueHelpDefinition on the field.

━━━━━━━━━━━━━━━━━━━━
▶ WHERE WE ARE

Part 2 made the data meaningful. Now you describe the screen. Fiori Elements generates list reports and object pages entirely from these annotations — no UI5 code.

━━━━━━━━━━━━━━━━━━━━
▶ 1. THE LIST REPORT

  • @UI.headerInfo (entity level) — typeName ('Purchase Request'), typeNamePlural, title (the field shown as object title), description.
  • @UI.lineItem: [{ position: 10, importance: #HIGH }] — a column in the table. position orders columns; importance decides what stays visible on small screens.
  • @UI.selectionField: [{ position: 10 }] — a field in the filter bar.
  • @UI.hidden: true — technical fields (UUIDs) never shown.

━━━━━━━━━━━━━━━━━━━━
▶ 2. THE OBJECT PAGE

The object page is built from facets:

  • @UI.facet on one element (usually the key) lists the sections: { id: 'General', purpose: #STANDARD, type: #IDENTIFICATION_REFERENCE, label: 'General', position: 10 }.
  • #IDENTIFICATION_REFERENCE shows all fields with @UI.identification.
  • #FIELDGROUP_REFERENCE with targetQualifier shows fields with @UI.fieldGroup: [{ qualifier: 'Amounts', position: 10 }].
  • #LINEITEM_REFERENCE with targetElement: '_Item' shows a table of child entities (their own @UI.lineItem).
  • #HEADER purpose puts data points or field groups into the header.

━━━━━━━━━━━━━━━━━━━━
▶ 3. ACTIONS AS BUTTONS

Add to an element's lineItem or identification:

{ type: #FOR_ACTION, dataAction: 'approve', label: 'Approve' }

The action must exist in the BDEF and projection; feature control enables or disables the button automatically.

━━━━━━━━━━━━━━━━━━━━
▶ 4. VALUE HELPS

@Consumption.valueHelpDefinition: [{ entity: { name: 'I_Currency', element: 'Currency' } }]

The value-help entity must be accessible (released view or your own) and, in RAP services, exposed or reachable through the service (Service Definitions Part 6).

━━━━━━━━━━━━━━━━━━━━
▶ 5. TEXT AND DISPLAY

  • @UI.textArrangement: #TEXT_FIRST — show "Completed (C)".
  • @UI.dataPoint for KPIs in the header, @UI.lineItem with criticality for colored status.
  • @EndUserText.label gives the column and field labels.

━━━━━━━━━━━━━━━━━━━━
▶ 6. WHERE TO PUT THEM

Put UI annotations into a metadata extension of the projection view (Part 4), not into the base BO view — the same BO can serve several apps with different layouts.

━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP

  1. Use the metadata extension in the code example for ZC_PurchReq.
  2. Add @Metadata.allowExtensions: true to ZC_PurchReq.
  3. Activate and open the service binding preview.
  4. Check: filter bar, columns, object page sections, items table, Approve button.

✅ CHECKPOINT: you can build a complete Fiori Elements UI from annotations.

Code example

ABAP Code
// ===== Metadata extension for the Purchase Request projection =====@Metadata.layer: #CUSTOMER@UI.headerInfo: {  typeName:       'Purchase Request',  typeNamePlural: 'Purchase Requests',  title:          { type: #STANDARD, value: 'RequestID' },  description:    { type: #STANDARD, value: 'Description' }}annotate entity ZC_PurchReq with{  // ---- object page sections (facets) ----  @UI.facet: [    { id: 'General', purpose: #STANDARD, type: #IDENTIFICATION_REFERENCE,      label: 'General Information', position: 10 },    { id: 'Amounts', purpose: #STANDARD, type: #FIELDGROUP_REFERENCE,      targetQualifier: 'Amounts', label: 'Amounts', position: 20 },    { id: 'Items',   purpose: #STANDARD, type: #LINEITEM_REFERENCE,      targetElement: '_Item', label: 'Items', position: 30 }  ]  @UI.hidden: true  RequestUUID;   // ---- list column + filter + object page field ----  @UI.lineItem:       [{ position: 10, importance: #HIGH }]  @UI.selectionField: [{ position: 10 }]  @UI.identification: [{ position: 10 }]  RequestID;   @UI.lineItem:       [{ position: 20, importance: #HIGH }]  @UI.identification: [{ position: 20 }]  Description;   @UI.lineItem:       [{ position: 30, importance: #MEDIUM },                       { type: #FOR_ACTION, dataAction: 'approve', label: 'Approve' }]  // button  @UI.selectionField: [{ position: 20 }]  @UI.identification: [{ position: 30 },                       { type: #FOR_ACTION, dataAction: 'approve', label: 'Approve' }]  @UI.textArrangement: #TEXT_FIRST  Status;   @UI.selectionField: [{ position: 30 }]  @UI.identification: [{ position: 40 }]  @Consumption.valueHelpDefinition: [{ entity: { name: 'I_Supplier', element: 'Supplier' } }]  Supplier;   @UI.lineItem:   [{ position: 40 }]  @UI.fieldGroup: [{ qualifier: 'Amounts', position: 10 }]  TotalAmount;   @UI.fieldGroup: [{ qualifier: 'Amounts', position: 20 }]  @Consumption.valueHelpDefinition: [{ entity: { name: 'I_Currency', element: 'Currency' } }]  CurrencyCode;} // Projection header needs:  @Metadata.allowExtensions: true// Items table on the object page uses ZC_PurchReqItem's own @UI.lineItem annotations.

Real project scenario

A team planned three weeks of UI5 development for a purchase-request app with list, filters, object page, item table and an approve button. A senior developer showed that Fiori Elements could generate all of it from annotations.
They built the metadata extension in two days, including value helps and a status column with criticality colors. Feature control from the BDEF automatically disabled the Approve button for non-submitted requests. The only custom UI5 work left was a small extension for a chart, and the app went to test two weeks early.

Common mistakes

  • UI annotations in the base BO view instead of a metadata extension on the projection.
  • Forgetting @Metadata.allowExtensions: true on the projection.
  • Facets pointing to a qualifier or element that does not exist.
  • Action buttons for actions not exposed in the projection BDEF.
  • Showing UUIDs instead of hiding them.
  • Value helps on entities the service cannot reach.

Best practices

  • Design the screen first: columns, filters, sections, actions — then annotate.
  • Use positions in steps of 10 to allow later insertions.
  • Use importance for responsive tables.
  • Hide technical keys; show readable IDs and texts.
  • Keep one metadata extension per projection and consumer.

Interview angle

Questions: "Which annotations build a Fiori Elements list report and object page?", "How do you add an action button?", "How do you add a value help?"
Strong answer: headerInfo, lineItem, selectionField for the list; facets with identification, fieldGroup and lineItem references for the object page; #FOR_ACTION entries for buttons (action must be in BDEF and projection, feature control handles enablement); @Consumption.valueHelpDefinition for value helps; all in a metadata extension of the projection.

Practice this lesson

Quick check

1. An object page shows 45 fields in one section. Which annotations structure it into sections?

2. A developer wants end users to be able to use the free-text search box in a Fiori Elements list report to find records based on a description field. What must be done at the CDS annotation level to support this?

3. You need a custom F4 value help for a field whose values come from a separate CDS view rather than the automatically derived association-based help. Which annotation should you use?

Interview questions

1. Build a Fiori Elements list report and object page for purchase requests with annotations only. Which annotations do you use?

Answer it in your own words first, then compare.

2. An object page lost its 'Financial Details' section after a refactor. What do you check?

Answer it in your own words first, then compare.

Practice more with Interview AI →

Reference-verified: the steps are checked against official SAP documentation and tutorials, and object and field names in the sample code are checked for consistency. The code has not been compiled or run on an SAP system by ERPClimb. Syntax marked release-dependent varies by SAP release, so check it in your own system.

More lessons in this topic

Interview questions on this topic

Related SAP topics