UI Annotationen für RAP: Fortgeschrittene Techniken für Fiori Elements

Kategorie
RAP
Veröffentlicht
Autor
Johannes

Mit den Grundlagen von UI-Annotationen erreichen Sie schnell erste Ergebnisse. Für professionelle Fiori Elements Apps brauchen Sie jedoch fortgeschrittene Techniken: strukturierte Seitenbereiche mit Facets, dynamische Hervorhebungen, kontextabhängige Sichtbarkeit und analytische Visualisierungen.

Facets: Die Seitenstruktur definieren

Facets bestimmen, wie die Object Page strukturiert ist. Sie definieren Bereiche, Tabs und Feldgruppen:

┌─────────────────────────────────────────────────────────────────────────┐
│ [HeaderInfo: Buchungsnummer 12345 - Müller, Hans] │
├─────────────────────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Allgemein │ │ Positionen │ │ Historie │ ← Facet Tabs │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
├─────────────────────────────────────────────────────────────────────────┤
│ ┌───────────────────────────┐ ┌───────────────────────────┐ │
│ │ Flugdaten │ │ Passagier │ │
│ │ ───────────────────── │ │ ───────────────────── │ │
│ │ Datum: 15.03.2026 │ │ Name: Hans Müller │ │
│ │ Abflug: Frankfurt │ │ Email: [email protected] │ │
│ │ Ankunft: New York │ │ Telefon: +49 123 456 │ │
│ └───────────────────────────┘ └───────────────────────────┘ │
│ ↑ FieldGroups │
└─────────────────────────────────────────────────────────────────────────┘

Facet-Hierarchie aufbauen

define view entity ZC_FlightBooking
as projection on ZI_FlightBooking
{
@UI.facet: [
-- Hauptbereich: Collection als Container
{
id: 'GeneralSection',
purpose: #STANDARD,
type: #COLLECTION,
label: 'Allgemeine Informationen',
position: 10
},
-- FieldGroup innerhalb der Collection
{
id: 'FlightData',
parentId: 'GeneralSection',
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'FlightData',
label: 'Flugdaten',
position: 10
},
{
id: 'PassengerData',
parentId: 'GeneralSection',
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'Passenger',
label: 'Passagier',
position: 20
},
-- Eigener Tab für Unterpositionen
{
id: 'ItemsSection',
purpose: #STANDARD,
type: #LINEITEM_REFERENCE,
label: 'Positionen',
position: 20,
targetElement: '_BookingItems'
},
-- Tab für Änderungshistorie
{
id: 'HistorySection',
purpose: #STANDARD,
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'AdminData',
label: 'Historie',
position: 30
}
]
key BookingId,
...
}

FieldGroups definieren

Die FieldGroups werden bei den einzelnen Feldern referenziert:

@UI.fieldGroup: [{ qualifier: 'FlightData', position: 10 }]
FlightDate,
@UI.fieldGroup: [{ qualifier: 'FlightData', position: 20 }]
DepartureAirport,
@UI.fieldGroup: [{ qualifier: 'FlightData', position: 30 }]
ArrivalAirport,
@UI.fieldGroup: [{ qualifier: 'Passenger', position: 10 }]
PassengerName,
@UI.fieldGroup: [{ qualifier: 'Passenger', position: 20 }]
@Semantics.eMail.address: true
Email,
@UI.fieldGroup: [{ qualifier: 'Passenger', position: 30 }]
@Semantics.telephone.type: [#WORK]
Phone,
@UI.fieldGroup: [{ qualifier: 'AdminData', position: 10 }]
CreatedBy,
@UI.fieldGroup: [{ qualifier: 'AdminData', position: 20 }]
CreatedAt,
@UI.fieldGroup: [{ qualifier: 'AdminData', position: 30 }]
LastChangedBy,
@UI.fieldGroup: [{ qualifier: 'AdminData', position: 40 }]
LastChangedAt

Facet-Typen im Überblick

TypVerwendung
#COLLECTIONContainer für mehrere FieldGroups
#FIELDGROUP_REFERENCEReferenziert FieldGroup-Felder
#LINEITEM_REFERENCETabelle mit Unterpositionen
#IDENTIFICATION_REFERENCEAutomatisch aus @UI.identification
#DATAPOINT_REFERENCEEinzelner DataPoint (z.B. KPI)
#CHART_REFERENCEEingebettetes Diagramm

HeaderInfo: Der Seitenkopf

HeaderInfo definiert, was im Header der Object Page angezeigt wird:

@UI.headerInfo: {
typeName: 'Flugbuchung',
typeNamePlural: 'Flugbuchungen',
title: {
type: #STANDARD,
value: 'BookingId',
label: 'Buchungsnummer'
},
description: {
type: #STANDARD,
value: 'PassengerName',
label: 'Passagier'
},
imageUrl: 'AirlineLogoUrl',
typeImageUrl: 'sap-icon://flight'
}
define view entity ZC_FlightBooking

Wichtige HeaderInfo-Eigenschaften:

EigenschaftBeschreibung
typeNameSingular-Bezeichnung der Entität
typeNamePluralPlural-Bezeichnung für Listen
titleHaupttitel im Header
descriptionUntertitel im Header
imageUrlDynamisches Bild (Feld mit URL)
typeImageUrlStatisches Icon

DataFieldForAction: Aktionsbuttons

Aktionen können in Listen und auf der Object Page platziert werden:

@UI: {
lineItem: [
-- Spalteninhalt
{ position: 10, importance: #HIGH },
-- Aktion in der Listenkopfzeile
{ position: 100, type: #FOR_ACTION, dataAction: 'confirmBooking', label: 'Bestätigen' },
{ position: 110, type: #FOR_ACTION, dataAction: 'cancelBooking', label: 'Stornieren' }
],
identification: [
{ position: 10 },
-- Aktion auf der Object Page
{ position: 100, type: #FOR_ACTION, dataAction: 'confirmBooking', label: 'Buchung bestätigen' }
]
}
key BookingId,

Aktionen mit Criticality

Aktionen können farblich hervorgehoben werden:

@UI.lineItem: [{
position: 110,
type: #FOR_ACTION,
dataAction: 'cancelBooking',
label: 'Stornieren',
criticality: #NEGATIVE -- Rot
}]
CriticalityFarbeVerwendung
#POSITIVEGrünBestätigen, Freigeben
#NEGATIVERotLöschen, Stornieren
#CRITICALOrangeWarnung, Pause

DataFieldForIntentBasedNavigation

Navigation zu anderen Fiori Apps per Intent:

@UI.lineItem: [{
position: 50,
type: #FOR_INTENT_BASED_NAVIGATION,
semanticObject: 'Customer',
action: 'display',
label: 'Kunde anzeigen'
}]
CustomerId,
-- Mit Parametern
@UI.lineItem: [{
position: 60,
type: #FOR_INTENT_BASED_NAVIGATION,
semanticObject: 'Flight',
action: 'manage',
label: 'Flug verwalten',
mapping: [{
localElement: 'FlightId',
semanticObjectAttribute: 'FlightId'
}]
}]
FlightId,

Voraussetzung: Die Ziel-App muss im SAP Fiori Launchpad mit entsprechendem Semantic Object und Action konfiguriert sein.

Criticality und Highlighting

Criticality ermöglicht dynamische Farbcodierung basierend auf Datenwerten:

Berechnetes Criticality-Feld

define view entity ZI_FlightBooking
{
BookingStatus,
-- Criticality als berechnetes Feld
case BookingStatus
when 'N' then 2 -- Neu: Gelb
when 'C' then 3 -- Bestätigt: Grün
when 'X' then 1 -- Storniert: Rot
else 0 -- Neutral: Grau
end as StatusCriticality,
FlightPrice,
-- Criticality für Preis
case
when FlightPrice > 2000 then 1 -- Rot: Teuer
when FlightPrice > 1000 then 2 -- Gelb: Mittel
else 3 -- Grün: Günstig
end as PriceCriticality,
}

Criticality in UI-Annotationen verwenden

@UI.lineItem: [{
position: 30,
importance: #HIGH,
criticality: 'StatusCriticality',
criticalityRepresentation: #WITH_ICON
}]
BookingStatus,
@UI.lineItem: [{
position: 40,
criticality: 'PriceCriticality'
}]
@Semantics.amount.currencyCode: 'Currency'
FlightPrice,
@UI.hidden: true
StatusCriticality,
@UI.hidden: true
PriceCriticality,

Criticality-Werte

WertBedeutungFarbeIcon
0NeutralGrau-
1NegativeRot
2CriticalGelb/Orange
3PositiveGrün
5New ItemBlau(speziell)

Conditional Visibility

Felder können basierend auf anderen Feldwerten ein- oder ausgeblendet werden:

Hidden mit dynamischem Wert

-- Feld nur für interne Nutzer sichtbar
@UI.hidden: #( IsExternalUser )
InternalNotes,
-- Das steuernde Feld (berechneter Boolean)
case
when UserType = 'EXTERNAL' then abap_true
else abap_false
end as IsExternalUser,

Conditional Visibility über Annotations

-- Feld nur anzeigen wenn Status = 'C' (bestätigt)
@UI.fieldGroup: [{
qualifier: 'ConfirmationData',
position: 10,
hidden: #( IsNotConfirmed )
}]
ConfirmationDate,
@UI.fieldGroup: [{
qualifier: 'ConfirmationData',
position: 20,
hidden: #( IsNotConfirmed )
}]
ConfirmedBy,
-- Steuerungsfeld
case when BookingStatus <> 'C' then abap_true else abap_false end as IsNotConfirmed,

Read-Only basierend auf Status

-- Felder nur bearbeitbar wenn Status = 'N' (neu)
@UI.fieldGroup: [{
qualifier: 'FlightData',
position: 10
}]
@ObjectModel.readOnly: #( IsNotEditable )
FlightDate,
case when BookingStatus <> 'N' then abap_true else abap_false end as IsNotEditable,

Chart Annotationen

Eingebettete Diagramme in der Object Page:

Micro Chart im LineItem

@UI.lineItem: [{
position: 60,
type: #AS_CHART,
valueQualifier: 'OccupancyChart'
}]
@UI.chart: [{
qualifier: 'OccupancyChart',
chartType: #BULLET,
measures: ['OccupancyRate'],
measureAttributes: [{
measure: 'OccupancyRate',
role: #AXIS_1
}],
description: 'Auslastung'
}]
@UI.dataPoint: {
qualifier: 'OccupancyChart',
targetValue: 100,
criticalityCalculation: {
improvementDirection: #MAXIMIZE,
toleranceRangeLowValue: 50,
deviationRangeLowValue: 25
}
}
OccupancyRate,

Chart in Facet

@UI.facet: [{
id: 'AnalyticsSection',
purpose: #STANDARD,
type: #CHART_REFERENCE,
targetQualifier: 'RevenueChart',
label: 'Umsatzentwicklung',
position: 40
}]
@UI.chart: [{
qualifier: 'RevenueChart',
chartType: #COLUMN,
dimensions: ['Month'],
measures: ['Revenue'],
dimensionAttributes: [{
dimension: 'Month',
role: #CATEGORY
}],
measureAttributes: [{
measure: 'Revenue',
role: #AXIS_1
}]
}]

Chart-Typen

ChartTypeBeschreibung
#COLUMNSäulendiagramm
#BARBalkendiagramm
#LINELiniendiagramm
#PIEKreisdiagramm
#DONUTRingdiagramm
#BULLETBullet Chart (Micro)
#COMPARISONVergleichschart

KPI Annotationen

Key Performance Indicators im Header:

@UI.headerInfo: {
typeName: 'Flugbuchung',
typeNamePlural: 'Flugbuchungen',
title: { type: #STANDARD, value: 'BookingId' }
}
@UI.facet: [{
id: 'KPIHeader',
purpose: #HEADER,
type: #DATAPOINT_REFERENCE,
targetQualifier: 'TotalRevenue',
position: 10
}]
define view entity ZC_FlightBooking
{
@UI.dataPoint: {
qualifier: 'TotalRevenue',
title: 'Gesamtumsatz',
criticalityCalculation: {
improvementDirection: #MAXIMIZE,
toleranceRangeLowValue: 10000,
deviationRangeLowValue: 5000
}
}
@Semantics.amount.currencyCode: 'Currency'
TotalRevenue,
}

Mehrere KPIs im Header

@UI.facet: [
{
id: 'KPI_Revenue',
purpose: #HEADER,
type: #DATAPOINT_REFERENCE,
targetQualifier: 'Revenue',
position: 10
},
{
id: 'KPI_Bookings',
purpose: #HEADER,
type: #DATAPOINT_REFERENCE,
targetQualifier: 'BookingCount',
position: 20
},
{
id: 'KPI_Occupancy',
purpose: #HEADER,
type: #DATAPOINT_REFERENCE,
targetQualifier: 'Occupancy',
position: 30
}
]
@UI.dataPoint: {
qualifier: 'Revenue',
title: 'Umsatz',
visualization: #NUMBER
}
TotalRevenue,
@UI.dataPoint: {
qualifier: 'BookingCount',
title: 'Buchungen',
visualization: #NUMBER
}
NumberOfBookings,
@UI.dataPoint: {
qualifier: 'Occupancy',
title: 'Auslastung',
visualization: #PROGRESS,
targetValue: 100
}
OccupancyPercent,

Vollständiges Flugbuchung-Beispiel

@EndUserText.label: 'Flugbuchung Projection'
@Metadata.allowExtensions: true
@UI.headerInfo: {
typeName: 'Flugbuchung',
typeNamePlural: 'Flugbuchungen',
title: { type: #STANDARD, value: 'BookingId' },
description: { type: #STANDARD, value: 'PassengerName' },
typeImageUrl: 'sap-icon://flight'
}
define view entity ZC_FlightBooking
as projection on ZI_FlightBooking
{
@UI.facet: [
-- Header KPIs
{
id: 'KPI_Price',
purpose: #HEADER,
type: #DATAPOINT_REFERENCE,
targetQualifier: 'FlightPrice',
position: 10
},
-- Hauptbereich
{
id: 'GeneralSection',
purpose: #STANDARD,
type: #COLLECTION,
label: 'Buchungsdetails',
position: 10
},
{
id: 'FlightData',
parentId: 'GeneralSection',
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'Flight',
label: 'Flugdaten',
position: 10
},
{
id: 'PassengerData',
parentId: 'GeneralSection',
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'Passenger',
label: 'Passagier',
position: 20
},
-- Admin-Bereich
{
id: 'AdminSection',
purpose: #STANDARD,
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'Admin',
label: 'Verwaltung',
position: 20
}
]
@UI: {
lineItem: [
{ position: 10, importance: #HIGH },
{ position: 100, type: #FOR_ACTION, dataAction: 'confirmBooking', label: 'Bestätigen' },
{ position: 110, type: #FOR_ACTION, dataAction: 'cancelBooking', label: 'Stornieren', criticality: #NEGATIVE }
],
identification: [
{ position: 10 },
{ position: 100, type: #FOR_ACTION, dataAction: 'confirmBooking', label: 'Buchung bestätigen' }
],
selectionField: [{ position: 10 }]
}
key BookingId,
@UI: {
lineItem: [{ position: 20, importance: #HIGH, criticality: 'StatusCriticality', criticalityRepresentation: #WITH_ICON }],
identification: [{ position: 20 }],
selectionField: [{ position: 20 }]
}
BookingStatus,
@UI.hidden: true
StatusCriticality,
@UI: {
lineItem: [{ position: 30, importance: #MEDIUM }],
fieldGroup: [{ qualifier: 'Flight', position: 10 }]
}
FlightDate,
@UI.fieldGroup: [{ qualifier: 'Flight', position: 20 }]
DepartureAirport,
@UI.fieldGroup: [{ qualifier: 'Flight', position: 30 }]
ArrivalAirport,
@UI: {
lineItem: [{ position: 40, importance: #HIGH }],
dataPoint: {
qualifier: 'FlightPrice',
title: 'Preis'
}
}
@Semantics.amount.currencyCode: 'Currency'
FlightPrice,
@UI.hidden: true
Currency,
@UI: {
lineItem: [{ position: 50, type: #FOR_INTENT_BASED_NAVIGATION, semanticObject: 'Customer', action: 'display' }],
fieldGroup: [{ qualifier: 'Passenger', position: 10 }]
}
PassengerName,
@UI.fieldGroup: [{ qualifier: 'Passenger', position: 20 }]
@Semantics.eMail.address: true
Email,
@UI.fieldGroup: [{ qualifier: 'Passenger', position: 30 }]
@Semantics.telephone.type: [#WORK]
Phone,
@UI.fieldGroup: [{ qualifier: 'Admin', position: 10, label: 'Erstellt von' }]
@Semantics.user.createdBy: true
CreatedBy,
@UI.fieldGroup: [{ qualifier: 'Admin', position: 20, label: 'Erstellt am' }]
@Semantics.systemDateTime.createdAt: true
CreatedAt,
@UI.fieldGroup: [{ qualifier: 'Admin', position: 30, label: 'Geändert von' }]
@Semantics.user.lastChangedBy: true
LastChangedBy,
@UI.fieldGroup: [{ qualifier: 'Admin', position: 40, label: 'Geändert am' }]
@Semantics.systemDateTime.lastChangedAt: true
LastChangedAt
}

Best Practices

AspektEmpfehlung
Facet-StrukturCollections für zusammengehörige FieldGroups nutzen
CriticalitySparsam einsetzen, nur bei echter Bedeutung (Status, Grenzwerte)
Hidden FieldsBerechnete Steuerungsfelder immer mit @UI.hidden: true
HeaderInfoAussagekräftigen Titel und Beschreibung wählen
ActionsWichtige Aktionen in lineItem, alle in identification
KPIsMax. 3-4 KPIs im Header für Übersichtlichkeit
ChartsMicro Charts für Trends, vollständige Charts in eigenen Facets
NavigationIntent-Based Navigation für konsistente App-zu-App-Navigation

Zusammenfassung

Fortgeschrittene UI-Annotationen ermöglichen professionelle Fiori Elements Apps ohne Frontend-Code. Mit Facets strukturieren Sie Seiten logisch, Criticality macht Status visuell erkennbar, und Charts/KPIs liefern Analysefähigkeiten direkt in der Anwendung.

Weiterführende Artikel: CDS Annotations Grundlagen für die Basics, RAP Actions und Functions für Aktionsimplementierung, RAP Nachrichten in Fiori für Benutzer-Feedback und Fiori Elements UI ohne Code für den Einstieg.