Annotations UI pour RAP : Techniques avancées pour Fiori Elements

Catégorie
RAP
Publié
Auteur
Johannes

Avec les bases des annotations UI, vous obtenez rapidement des premiers résultats. Cependant, pour des applications Fiori Elements professionnelles, vous avez besoin de techniques avancées : sections de page structurées avec Facets, mises en évidence dynamiques, visibilité contextuelle et visualisations analytiques.

Facets : Définir la structure de la page

Les Facets déterminent comment l’Object Page est structurée. Elles définissent des sections, des onglets et des groupes de champs :

┌─────────────────────────────────────────────────────────────────────────┐
│ [HeaderInfo: Numéro de réservation 12345 - Müller, Hans] │
├─────────────────────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Général │ │ Positions │ │ Historique │ <- Onglets Facet │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
├─────────────────────────────────────────────────────────────────────────┤
│ ┌───────────────────────────┐ ┌───────────────────────────┐ │
│ │ Données de vol │ │ Passager │ │
│ │ ───────────────────── │ │ ───────────────────── │ │
│ │ Date: 15.03.2026 │ │ Nom: Hans Müller │ │
│ │ Départ: Francfort │ │ Email: [email protected] │ │
│ │ Arrivée: New York │ │ Téléphone: +49 123 456 │ │
│ └───────────────────────────┘ └───────────────────────────┘ │
│ ^ FieldGroups │
└─────────────────────────────────────────────────────────────────────────┘

Construire une hiérarchie de Facets

define view entity ZC_FlightBooking
as projection on ZI_FlightBooking
{
@UI.facet: [
-- Section principale : Collection comme conteneur
{
id: 'GeneralSection',
purpose: #STANDARD,
type: #COLLECTION,
label: 'Informations générales',
position: 10
},
-- FieldGroup dans la Collection
{
id: 'FlightData',
parentId: 'GeneralSection',
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'FlightData',
label: 'Données de vol',
position: 10
},
{
id: 'PassengerData',
parentId: 'GeneralSection',
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'Passenger',
label: 'Passager',
position: 20
},
-- Onglet propre pour les sous-positions
{
id: 'ItemsSection',
purpose: #STANDARD,
type: #LINEITEM_REFERENCE,
label: 'Positions',
position: 20,
targetElement: '_BookingItems"
},
-- Onglet pour l'historique des modifications
{
id: 'HistorySection',
purpose: #STANDARD,
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'AdminData',
label: 'Historique',
position: 30
}
]
key BookingId,
...
}

Définir les FieldGroups

Les FieldGroups sont référencés au niveau des champs individuels :

@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

Aperçu des types de Facets

TypeUtilisation
#COLLECTIONConteneur pour plusieurs FieldGroups
#FIELDGROUP_REFERENCERéférence les champs FieldGroup
#LINEITEM_REFERENCETable avec sous-positions
#IDENTIFICATION_REFERENCEAutomatiquement depuis @UI.identification
#DATAPOINT_REFERENCEDataPoint unique (ex. KPI)
#CHART_REFERENCEDiagramme intégré

HeaderInfo : L’en-tête de la page

HeaderInfo définit ce qui est affiché dans l’en-tête de l’Object Page :

@UI.headerInfo: {
typeName: 'Réservation de vol',
typeNamePlural: 'Réservations de vol',
title: {
type: #STANDARD,
value: 'BookingId',
label: 'Numéro de réservation"
},
description: {
type: #STANDARD,
value: 'PassengerName',
label: 'Passager"
},
imageUrl: 'AirlineLogoUrl',
typeImageUrl: 'sap-icon://flight"
}
define view entity ZC_FlightBooking

Propriétés importantes de HeaderInfo :

PropriétéDescription
typeNameDésignation singulière de l’entité
typeNamePluralDésignation plurielle pour les listes
titleTitre principal dans l’en-tête
descriptionSous-titre dans l’en-tête
imageUrlImage dynamique (champ avec URL)
typeImageUrlIcône statique

DataFieldForAction : Boutons d’action

Les actions peuvent être placées dans les listes et sur l’Object Page :

@UI: {
lineItem: [
-- Contenu de la colonne
{ position: 10, importance: #HIGH },
-- Action dans l'en-tête de la liste
{ position: 100, type: #FOR_ACTION, dataAction: 'confirmBooking', label: 'Confirmer' },
{ position: 110, type: #FOR_ACTION, dataAction: 'cancelBooking', label: 'Annuler' }
],
identification: [
{ position: 10 },
-- Action sur l'Object Page
{ position: 100, type: #FOR_ACTION, dataAction: 'confirmBooking', label: 'Confirmer la réservation' }
]
}
key BookingId,

Actions avec Criticality

Les actions peuvent être mises en évidence par des couleurs :

@UI.lineItem: [{
position: 110,
type: #FOR_ACTION,
dataAction: 'cancelBooking',
label: 'Annuler',
criticality: #NEGATIVE -- Rouge
}]
CriticalityCouleurUtilisation
#POSITIVEVertConfirmer, Valider
#NEGATIVERougeSupprimer, Annuler
#CRITICALOrangeAvertissement, Pause

DataFieldForIntentBasedNavigation

Navigation vers d’autres applications Fiori par Intent :

@UI.lineItem: [{
position: 50,
type: #FOR_INTENT_BASED_NAVIGATION,
semanticObject: 'Customer',
action: 'display',
label: 'Afficher le client"
}]
CustomerId,
-- Avec paramètres
@UI.lineItem: [{
position: 60,
type: #FOR_INTENT_BASED_NAVIGATION,
semanticObject: 'Flight',
action: 'manage',
label: 'Gérer le vol',
mapping: [{
localElement: 'FlightId',
semanticObjectAttribute: 'FlightId"
}]
}]
FlightId,

Prérequis : L’application cible doit être configurée dans le SAP Fiori Launchpad avec le Semantic Object et l’Action correspondants.

Criticality et mise en évidence

Criticality permet un codage couleur dynamique basé sur les valeurs des données :

Champ Criticality calculé

define view entity ZI_FlightBooking
{
BookingStatus,
-- Criticality comme champ calculé
case BookingStatus
when 'N' then 2 -- Nouveau : Jaune
when 'C' then 3 -- Confirmé : Vert
when 'X' then 1 -- Annulé : Rouge
else 0 -- Neutre : Gris
end as StatusCriticality,
FlightPrice,
-- Criticality pour le prix
case
when FlightPrice > 2000 then 1 -- Rouge : Cher
when FlightPrice > 1000 then 2 -- Jaune : Moyen
else 3 -- Vert : Abordable
end as PriceCriticality,
}

Utiliser Criticality dans les annotations UI

@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,

Valeurs de Criticality

ValeurSignificationCouleurIcône
0NeutreGris-
1NégatifRougeX
2CritiqueJaune/Orange!
3PositifVertV
5Nouvel élémentBleu(spécial)

Visibilité conditionnelle

Les champs peuvent être affichés ou masqués en fonction d’autres valeurs de champs :

Hidden avec valeur dynamique

-- Champ visible uniquement pour les utilisateurs internes
@UI.hidden: #( IsExternalUser )
InternalNotes,
-- Le champ de contrôle (Boolean calculé)
case
when UserType = 'EXTERNAL' then abap_true
else abap_false
end as IsExternalUser,

Visibilité conditionnelle via Annotations

-- Afficher le champ uniquement si Status = 'C' (confirmé)
@UI.fieldGroup: [{
qualifier: 'ConfirmationData',
position: 10,
hidden: #( IsNotConfirmed )
}]
ConfirmationDate,
@UI.fieldGroup: [{
qualifier: 'ConfirmationData',
position: 20,
hidden: #( IsNotConfirmed )
}]
ConfirmedBy,
-- Champ de contrôle
case when BookingStatus <> 'C' then abap_true else abap_false end as IsNotConfirmed,

Lecture seule basée sur le statut

-- Champs modifiables uniquement si Status = 'N' (nouveau)
@UI.fieldGroup: [{
qualifier: 'FlightData',
position: 10
}]
@ObjectModel.readOnly: #( IsNotEditable )
FlightDate,
case when BookingStatus <> 'N' then abap_true else abap_false end as IsNotEditable,

Annotations Chart

Diagrammes intégrés dans l’Object Page :

Micro Chart dans 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: 'Taux d''occupation"
}]
@UI.dataPoint: {
qualifier: 'OccupancyChart',
targetValue: 100,
criticalityCalculation: {
improvementDirection: #MAXIMIZE,
toleranceRangeLowValue: 50,
deviationRangeLowValue: 25
}
}
OccupancyRate,

Chart dans Facet

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

Types de Charts

ChartTypeDescription
#COLUMNDiagramme en colonnes
#BARDiagramme en barres
#LINEDiagramme linéaire
#PIEDiagramme circulaire
#DONUTDiagramme en anneau
#BULLETBullet Chart (Micro)
#COMPARISONChart de comparaison

Annotations KPI

Key Performance Indicators dans l’en-tête :

@UI.headerInfo: {
typeName: 'Réservation de vol',
typeNamePlural: 'Réservations de vol',
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: 'Chiffre d''affaires total',
criticalityCalculation: {
improvementDirection: #MAXIMIZE,
toleranceRangeLowValue: 10000,
deviationRangeLowValue: 5000
}
}
@Semantics.amount.currencyCode: 'Currency"
TotalRevenue,
}

Plusieurs KPIs dans l’en-tête

@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: 'Chiffre d''affaires',
visualization: #NUMBER
}
TotalRevenue,
@UI.dataPoint: {
qualifier: 'BookingCount',
title: 'Réservations',
visualization: #NUMBER
}
NumberOfBookings,
@UI.dataPoint: {
qualifier: 'Occupancy',
title: 'Occupation',
visualization: #PROGRESS,
targetValue: 100
}
OccupancyPercent,

Exemple complet de réservation de vol

@EndUserText.label: 'Projection réservation de vol"
@Metadata.allowExtensions: true
@UI.headerInfo: {
typeName: 'Réservation de vol',
typeNamePlural: 'Réservations de vol',
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: [
-- KPIs en-tête
{
id: 'KPI_Price',
purpose: #HEADER,
type: #DATAPOINT_REFERENCE,
targetQualifier: 'FlightPrice',
position: 10
},
-- Section principale
{
id: 'GeneralSection',
purpose: #STANDARD,
type: #COLLECTION,
label: 'Détails de la réservation',
position: 10
},
{
id: 'FlightData',
parentId: 'GeneralSection',
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'Flight',
label: 'Données de vol',
position: 10
},
{
id: 'PassengerData',
parentId: 'GeneralSection',
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'Passenger',
label: 'Passager',
position: 20
},
-- Section admin
{
id: 'AdminSection',
purpose: #STANDARD,
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'Admin',
label: 'Administration',
position: 20
}
]
@UI: {
lineItem: [
{ position: 10, importance: #HIGH },
{ position: 100, type: #FOR_ACTION, dataAction: 'confirmBooking', label: 'Confirmer' },
{ position: 110, type: #FOR_ACTION, dataAction: 'cancelBooking', label: 'Annuler', criticality: #NEGATIVE }
],
identification: [
{ position: 10 },
{ position: 100, type: #FOR_ACTION, dataAction: 'confirmBooking', label: 'Confirmer la réservation' }
],
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: 'Prix"
}
}
@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: 'Créé par' }]
@Semantics.user.createdBy: true
CreatedBy,
@UI.fieldGroup: [{ qualifier: 'Admin', position: 20, label: 'Créé le' }]
@Semantics.systemDateTime.createdAt: true
CreatedAt,
@UI.fieldGroup: [{ qualifier: 'Admin', position: 30, label: 'Modifié par' }]
@Semantics.user.lastChangedBy: true
LastChangedBy,
@UI.fieldGroup: [{ qualifier: 'Admin', position: 40, label: 'Modifié le' }]
@Semantics.systemDateTime.lastChangedAt: true
LastChangedAt
}

Bonnes pratiques

AspectRecommandation
Structure des FacetsUtiliser des Collections pour les FieldGroups liés
CriticalityUtiliser avec parcimonie, uniquement pour une vraie signification (Statut, seuils)
Champs HiddenToujours marquer les champs de contrôle calculés avec @UI.hidden: true
HeaderInfoChoisir un titre et une description parlants
ActionsActions importantes dans lineItem, toutes dans identification
KPIsMax. 3-4 KPIs dans l’en-tête pour la clarté
ChartsMicro Charts pour les tendances, Charts complets dans des Facets propres
NavigationNavigation basée sur Intent pour une navigation cohérente entre apps

Résumé

Les annotations UI avancées permettent des applications Fiori Elements professionnelles sans code frontend. Avec les Facets, vous structurez les pages logiquement, Criticality rend les statuts visuellement reconnaissables, et les Charts/KPIs fournissent des capacités analytiques directement dans l’application.

Articles connexes : Bases des annotations CDS pour les fondamentaux, Actions et Functions RAP pour l’implémentation des actions, Messages RAP dans Fiori pour le feedback utilisateur et Fiori Elements UI sans code pour débuter.