Fiori Elements
RAP / CDS / ODataintermediate

Fiori Elements Part 3: Designing Apps with UI Annotations

Key takeaway

Learn how to configure List Report and Object Page floorplans in detail using @UI annotations, headers, facets, tables, and actions wired to RAP behavior, including runtime binding to OData V4.

Explanation

📌 KEY POINTS
✅ Design the screen first: filters, columns, header, sections, actions — then annotate.

✅ Key annotations: headerInfo, lineItem, selectionField, facet, fieldGroup, identification, dataPoint.

✅ Put UI annotations in metadata extensions of the projection.

💡 Use importance and criticality for responsive, scannable tables.

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

Part 2 generated an app from a RAP service. Now we design what it shows, using the @UI annotation vocabulary.

━━━━━━━━━━━━━━━━━━━━
▶ 1. DESIGN BEFORE ANNOTATING

  • Sketch with the business: filters, table columns, object page header, sections, actions.
  • Map each element to an annotation before writing any.
  • Put all @UI annotations into the metadata extension of the projection (layer #CORE).

━━━━━━━━━━━━━━━━━━━━
▶ 2. LIST REPORT ANNOTATIONS

  • @UI.selectionField: [{ position: 10 }] — filter bar fields.
  • @UI.lineItem: [{ position: 10, importance: #HIGH }] — table columns; importance drives responsive hiding.
  • @UI.lineItem with type: #FOR_ACTION, dataAction: 'acceptTravel' — action button in the table toolbar.
  • @UI.presentationVariant — default sort order and grouping.

━━━━━━━━━━━━━━━━━━━━
▶ 3. OBJECT PAGE HEADER

  • @UI.headerInfo: typeName, typeNamePlural, title, description.
  • @UI.dataPoint with criticality for status/KPI in the header.
  • Header facets (purpose: #HEADER) show data points.

━━━━━━━━━━━━━━━━━━━━
▶ 4. OBJECT PAGE SECTIONS

  • @UI.facet: sections of type #IDENTIFICATION_REFERENCE, #FIELDGROUP_REFERENCE, #LINEITEM_REFERENCE (child table via targetElement: '_Booking').
  • @UI.fieldGroup: [{ qualifier: 'Dates', position: 10 }] groups fields inside a section.
  • @UI.identification: fields and actions of the general section.

━━━━━━━━━━━━━━━━━━━━
▶ 5. CRITICALITY, TEXTS AND VALUE HELPS

  • criticality: 'StatusCriticality' — a field with 0–3 colors values (neutral, red, yellow, green).
  • @ObjectModel.text.element and @UI.textArrangement: #TEXT_FIRST show "Name (ID)".
  • @Consumption.valueHelpDefinition on the projection field for F4 help.

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

  1. Write the screen sketch as a table: element → annotation.
  2. Add selectionField and lineItem with importance.
  3. Add headerInfo, header dataPoint with criticality.
  4. Add facets, fieldGroups and the child table section.
  5. Add action buttons via lineItem/identification with #FOR_ACTION.

✅ CHECKPOINT: the object page shows header status in color, two field groups and the bookings table.

Code example

ABAP Code
// Object Page facets and field groups for a Travel Object Pageannotate view ZC_Travel_FE with{  @UI.facet: [    { id: 'GeneralInfo', purpose: #STANDARD, type: #IDENTIFICATION_REFERENCE, label: 'General Information', position: 10 },    { id: 'Bookings', purpose: #STANDARD, type: #LINEITEM_REFERENCE, label: 'Bookings', targetElement: '_Booking', position: 20 }  ]   @UI.fieldGroup: [ { qualifier: 'Header', position: 10 } ]  @UI.identification: [ { position: 10, fieldGroup: 'Header' } ]  TravelId;   @UI.fieldGroup: [ { qualifier: 'Header', position: 20 } ]  @UI.identification: [ { position: 20, fieldGroup: 'Header' } ]  @UI.criticality: #OverallStatusCriticality  OverallStatus;   @Semantics.amount.currencyCode: 'CurrencyCode'  @UI.lineItem: [ { position: 30, importance: #HIGH } ]  @UI.fieldGroup: [ { qualifier: 'Header', position: 30 } ]  TotalPrice;} // Criticality mapping element (referenced above)define transient view entity ZC_Travel_Criticality_Helper  as select from ZR_Travel{  key TravelUUID as TravelUuid,  case OverallStatus    when 'A' then 3   /* accepted - green */    when 'X' then 1   /* rejected - red */    else 2            /* open - yellow */  end as OverallStatusCriticality}

Real project scenario

A procurement team's Manage Purchase Requisitions app needs a status column colored red/yellow/green, a filter bar limited to plant, requisition type, and date range, and an Object Page showing header data plus an embedded editable table of requisition line items. All of this is delivered purely through @UI.lineItem, @UI.selectionField, @UI.facet, and @UI.criticality annotations on the projection view and its composition child, with the development team spending review time only on the underlying RAP behavior (validations, determinations) rather than any UI5 view code.

Common mistakes

  • Overloading the List Report filter bar with too many @UI.selectionField entries, degrading usability and performance because the smart filter bar issues a combined OData query with excessive parameters.
  • Forgetting that @UI.lineItem importance levels only affect responsive behavior, not column order - developers sometimes mistakenly rely on importance to reorder columns.
  • Hardcoding criticality values instead of deriving them from a calculated/transient element, making the annotation brittle when status codes change.
  • Adding facets referencing associations that are not properly exposed or authorized in the projection view, resulting in an empty or erroring Object Page section at runtime.
  • Not testing annotation changes with a full service metadata refresh, leading to false 'it doesn't work' bug reports that are actually caching issues.

Best practices

  • Keep the filter bar lean - only include selectionFields that map to real, indexed, commonly-used search criteria.
  • Derive criticality and status-driven UI behavior from calculated CDS elements or RAP determinations rather than embedding logic in the UI layer.
  • Use @UI.lineItem importance intentionally for responsive design, and control column order via explicit position values.
  • Structure Object Page facets to mirror the business object's composition hierarchy so navigation matches the user's mental model of the document.
  • Always verify annotation changes against the live service metadata preview before handing off to functional testers, to eliminate caching-related false defects.

Interview angle

Expect scenario questions like 'how would you show a colored status badge in a Fiori list without custom JavaScript?' The expected answer references @UI.criticality bound to a calculated CDS element, demonstrating the annotation-first mindset. Interviewers also probe understanding of facet types (#IDENTIFICATION_REFERENCE vs #LINEITEM_REFERENCE) to assess real hands-on experience versus theoretical knowledge.

Practice this lesson

Quick check

1. An object page should show general data, amounts and an item table as sections. What defines these sections?

2. Which annotation is used on a CDS view field to enable an OData value help (F4 dropdown) sourced from another CDS entity in a Fiori Elements app?

3. Which annotation is used at entity level to specify that the List Report results should render as a Grid Table instead of the default Responsive Table?

Interview questions

1. Walk through building a purchase request app with Fiori Elements on RAP.

Answer it in your own words first, then compare.

2. Which UI annotations do you need for a complete list report and object page, and where do you put them?

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