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 }] LastChangedAtAperçu des types de Facets
| Type | Utilisation |
|---|---|
#COLLECTION | Conteneur pour plusieurs FieldGroups |
#FIELDGROUP_REFERENCE | Référence les champs FieldGroup |
#LINEITEM_REFERENCE | Table avec sous-positions |
#IDENTIFICATION_REFERENCE | Automatiquement depuis @UI.identification |
#DATAPOINT_REFERENCE | DataPoint unique (ex. KPI) |
#CHART_REFERENCE | Diagramme 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_FlightBookingPropriétés importantes de HeaderInfo :
| Propriété | Description |
|---|---|
typeName | Désignation singulière de l’entité |
typeNamePlural | Désignation plurielle pour les listes |
title | Titre principal dans l’en-tête |
description | Sous-titre dans l’en-tête |
imageUrl | Image dynamique (champ avec URL) |
typeImageUrl | Icô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}]| Criticality | Couleur | Utilisation |
|---|---|---|
#POSITIVE | Vert | Confirmer, Valider |
#NEGATIVE | Rouge | Supprimer, Annuler |
#CRITICAL | Orange | Avertissement, 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: trueStatusCriticality,
@UI.hidden: truePriceCriticality,Valeurs de Criticality
| Valeur | Signification | Couleur | Icône |
|---|---|---|---|
| 0 | Neutre | Gris | - |
| 1 | Négatif | Rouge | X |
| 2 | Critique | Jaune/Orange | ! |
| 3 | Positif | Vert | V |
| 5 | Nouvel élément | Bleu | (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_falseend 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ôlecase 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
| ChartType | Description |
|---|---|
#COLUMN | Diagramme en colonnes |
#BAR | Diagramme en barres |
#LINE | Diagramme linéaire |
#PIE | Diagramme circulaire |
#DONUT | Diagramme en anneau |
#BULLET | Bullet Chart (Micro) |
#COMPARISON | Chart 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
| Aspect | Recommandation |
|---|---|
| Structure des Facets | Utiliser des Collections pour les FieldGroups liés |
| Criticality | Utiliser avec parcimonie, uniquement pour une vraie signification (Statut, seuils) |
| Champs Hidden | Toujours marquer les champs de contrôle calculés avec @UI.hidden: true |
| HeaderInfo | Choisir un titre et une description parlants |
| Actions | Actions importantes dans lineItem, toutes dans identification |
| KPIs | Max. 3-4 KPIs dans l’en-tête pour la clarté |
| Charts | Micro Charts pour les tendances, Charts complets dans des Facets propres |
| Navigation | Navigation 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.