Le List Report est l’un des templates Fiori Elements les plus utilisés. Il affiche les données sous forme de tableau et offre des filtres, un tri et des actions. Via les annotations CDS, vous pouvez personnaliser l’apparence en détail – sans une ligne de code UI5.
Structure de base d’un List Report
Un List Report se compose de plusieurs zones :
┌─────────────────────────────────────────────────────────┐│ Zone d'en-tête ││ ┌───────────────────────────────────────────────────┐ ││ │ Header Facets (KPI, graphiques, statut) │ ││ └───────────────────────────────────────────────────┘ │├─────────────────────────────────────────────────────────┤│ Barre de filtres ││ [Champ 1 ▼] [Champ 2 ▼] [Champ 3 ▼] [Go] [Adapter] │├─────────────────────────────────────────────────────────┤│ Barre d'outils tableau ││ [Créer] [Supprimer] [Action perso] │├─────────────────────────────────────────────────────────┤│ Contenu tableau ││ | Col 1 | Col 2 | Col 3 | Col 4 | ││ |-------|-------|-------|-------| ││ | Ligne 1 | ... | ... | ... | ││ | Ligne 2 | ... | ... | ... | │└─────────────────────────────────────────────────────────┘Annotation @UI.facet en détail
L’annotation @UI.facet est la clé pour personnaliser les List Reports et Object Pages. Elle définit quelles facettes (sections) sont affichées et comment elles sont structurées.
Types de facettes
| Type | Description | Utilisation |
|---|---|---|
#HEADER_SECTION | Zone dans l’en-tête | KPI, indicateurs de statut |
#COLLECTION | Conteneur pour plusieurs facettes | Groupement |
#IDENTIFICATION_REFERENCE | Champs d’identification standard | En-tête Object Page |
#LINEITEM_REFERENCE | Vue tableau | Entités subordonnées |
#DATAPOINT_REFERENCE | Point de données unique | KPI, indicateur |
#CHART_REFERENCE | Graphique | Visualisations |
#FIELDGROUP_REFERENCE | Groupe de champs | Zones de formulaire |
Structure de base d’une définition de facette
@UI.facet: [{ id: 'HeaderFacetID', -- ID unique purpose: #HEADER, -- #HEADER ou #STANDARD type: #DATAPOINT_REFERENCE, -- Type de facette targetQualifier: 'TotalAmount', -- Référence à @UI.dataPoint label: 'Montant total', -- Texte d'affichage position: 10 -- Ordre}]Header et Collection Facets : La différence
Les Header Facets apparaissent dans la zone supérieure (en-tête) d’un List Report ou d’une Object Page. Elles affichent des informations condensées comme des KPI ou des statuts.
Les Collection Facets sont des conteneurs qui regroupent plusieurs facettes. Elles apparaissent généralement dans la zone de contenu de l’Object Page.
@UI.facet: [ -- Header Facets (en haut dans l'en-tête) { id: 'HeaderKPI', purpose: #HEADER, -- Zone d'en-tête type: #DATAPOINT_REFERENCE, targetQualifier: 'TotalOrders', position: 10 },
-- Collection Facet (zone de contenu) { id: 'GeneralInfo', purpose: #STANDARD, -- Zone de contenu type: #COLLECTION, -- Conteneur label: 'Informations générales', position: 20 }, { id: 'Details', purpose: #STANDARD, type: #FIELDGROUP_REFERENCE, targetQualifier: 'Details', parentId: 'GeneralInfo', -- Subordonné position: 10 }]Header Facets personnalisés (KPI, indicateurs de statut)
Les Header Facets sont parfaits pour les KPI et les affichages de statut.
KPI avec DataPoint
@Metadata.allowExtensions: truedefine view entity ZC_SalesOrder as projection on ZI_SalesOrder{ key SalesOrderId,
@UI.dataPoint: { qualifier: 'TotalAmount', title: 'Valeur de commande', valueFormat: { numberOfFractionalDigits: 2 } } @Semantics.amount.currencyCode: 'CurrencyCode" TotalAmount,
CurrencyCode,
@UI.dataPoint: { qualifier: 'ItemCount', title: 'Positions', valueFormat: { numberOfFractionalDigits: 0 } } NumberOfItems,
@UI.dataPoint: { qualifier: 'OrderStatus', title: 'Statut', criticality: 'StatusCriticality" } Status,
StatusCriticality}La définition de facette correspondante :
@UI.facet: [ { id: 'TotalAmountHeader', purpose: #HEADER, type: #DATAPOINT_REFERENCE, targetQualifier: 'TotalAmount', position: 10 }, { id: 'ItemCountHeader', purpose: #HEADER, type: #DATAPOINT_REFERENCE, targetQualifier: 'ItemCount', position: 20 }, { id: 'StatusHeader', purpose: #HEADER, type: #DATAPOINT_REFERENCE, targetQualifier: 'OrderStatus', position: 30 }]Statut avec Criticality
La Criticality détermine la couleur de l’indicateur de statut :
| Valeur | Signification | Couleur |
|---|---|---|
| 0 | Neutre | Gris |
| 1 | Négatif | Rouge |
| 2 | Critique | Orange |
| 3 | Positif | Vert |
define view entity ZC_Order as projection on ZI_Order{ key OrderId,
Status,
-- Calcul de la Criticality case Status when 'OPEN' then 0 -- Gris when 'PENDING' then 2 -- Orange when 'COMPLETED' then 3 -- Vert when 'CANCELLED' then 1 -- Rouge else 0 end as StatusCriticality}Sections personnalisées dans le List Report
Les sections structurent la zone de contenu. Avec #COLLECTION, vous créez des sections groupées.
Plusieurs sections avec groupes de champs
@UI.facet: [ -- Section 1 : En-tête de commande { id: 'OrderHeader', purpose: #STANDARD, type: #COLLECTION, label: 'En-tête de commande', position: 10 }, { id: 'BasicData', purpose: #STANDARD, type: #FIELDGROUP_REFERENCE, targetQualifier: 'BasicData', parentId: 'OrderHeader', label: 'Données de base', position: 10 }, { id: 'Dates', purpose: #STANDARD, type: #FIELDGROUP_REFERENCE, targetQualifier: 'Dates', parentId: 'OrderHeader', label: 'Échéances', position: 20 },
-- Section 2 : Positions { id: 'OrderItems', purpose: #STANDARD, type: #LINEITEM_REFERENCE, targetElement: '_Items', label: 'Positions', position: 20 },
-- Section 3 : Notes { id: 'Notes', purpose: #STANDARD, type: #COLLECTION, label: 'Notes & pièces jointes', position: 30 }]Définir des groupes de champs
define view entity ZC_Order{ key OrderId,
@UI.fieldGroup: [{ qualifier: 'BasicData', position: 10 }] CustomerId,
@UI.fieldGroup: [{ qualifier: 'BasicData', position: 20 }] CustomerName,
@UI.fieldGroup: [{ qualifier: 'BasicData', position: 30 }] ShipToAddress,
@UI.fieldGroup: [{ qualifier: 'Dates', position: 10 }] OrderDate,
@UI.fieldGroup: [{ qualifier: 'Dates', position: 20 }] RequestedDeliveryDate,
@UI.fieldGroup: [{ qualifier: 'Dates', position: 30 }] ActualDeliveryDate}Conditional Facets (dépendant des données)
Les Conditional Facets ne sont affichées que lorsque certaines conditions sont remplies. Cela se fait via la propriété hidden.
Masquer une facette en fonction du statut
@UI.facet: [ { id: 'ShippingInfo', purpose: #STANDARD, type: #FIELDGROUP_REFERENCE, targetQualifier: 'Shipping', label: 'Informations d''expédition', position: 20, hidden: 'HideShipping' -- Référence au champ calculé }]
define view entity ZC_Order{ key OrderId, Status,
-- Info expédition uniquement pour certains statuts case when Status in ('SHIPPED', 'DELIVERED') then abap_false else abap_true end as HideShipping,
@UI.fieldGroup: [{ qualifier: 'Shipping', position: 10 }] TrackingNumber,
@UI.fieldGroup: [{ qualifier: 'Shipping', position: 20 }] Carrier,
@UI.fieldGroup: [{ qualifier: 'Shipping', position: 30 }] ShippedDate}Combiner plusieurs conditions
define view entity ZC_Contract{ key ContractId,
ContractType, Status,
-- Facette uniquement pour contrats de service actifs case when ContractType = 'SERVICE" and Status = 'ACTIVE" then abap_false else abap_true end as HideServiceDetails,
-- Facette uniquement pour contrats avec option de renouvellement case when HasRenewalOption = abap_true then abap_false else abap_true end as HideRenewalInfo}Intégration de graphiques dans l’en-tête
Les graphiques dans l’en-tête visualisent les données d’un coup d’œil.
Micro Chart dans l’en-tête
@UI.facet: [{ id: 'SalesChart', purpose: #HEADER, type: #CHART_REFERENCE, targetQualifier: 'SalesTrend', position: 40}]
define view entity ZC_SalesOverview{ key SalesOrgId,
@UI.chart: [{ qualifier: 'SalesTrend', chartType: #COLUMN, title: 'Chiffre d''affaires mensuel', measures: ['Revenue'], dimensions: ['Month'] }] @Aggregation.default: #SUM Revenue,
Month}Différents types de graphiques
-- Bullet Chart pour atteinte d'objectif@UI.chart: [{ qualifier: 'TargetAchievement', chartType: #BULLET, title: 'Atteinte d''objectif', measures: ['ActualValue'], measureAttributes: [{ measure: 'ActualValue', role: #AXIS_1, asDataPoint: true }]}]
@UI.dataPoint: { qualifier: 'ActualValue', targetValue: 'TargetValue', forecastValue: 'ForecastValue', minimumValue: 0, criticality: 'AchievementCriticality"}ActualValue,TargetValue,ForecastValue,
-- Radial Chart pour affichage en pourcentage@UI.chart: [{ qualifier: 'CompletionRate', chartType: #DONUT, title: 'Taux d''achèvement', measures: ['CompletedPercent']}]CompletedPercentGraphique avec couleurs Criticality
define view entity ZC_ProjectStatus{ key ProjectId,
@UI.chart: [{ qualifier: 'BudgetChart', chartType: #BULLET, title: 'Budget', measures: ['SpentBudget'], measureAttributes: [{ measure: 'SpentBudget', role: #AXIS_1, asDataPoint: true }] }] @UI.dataPoint: { qualifier: 'SpentBudget', targetValue: 'TotalBudget', criticality: 'BudgetCriticality" } SpentBudget,
TotalBudget,
-- Calculer la Criticality case when SpentBudget <= TotalBudget * 0.8 then 3 -- Vert when SpentBudget <= TotalBudget then 2 -- Orange else 1 -- Rouge end as BudgetCriticality}Exemple complet : Vue d’ensemble des ventes
@Metadata.allowExtensions: true@UI.headerInfo: { typeName: 'Document de vente', typeNamePlural: 'Documents de vente', title: { value: 'SalesOrderId' }, description: { value: 'CustomerName' }}define view entity ZC_SalesOrderReport as projection on ZI_SalesOrder{ -- Définitions de facettes @UI.facet: [ -- Header Facets { id: 'TotalValueHeader', purpose: #HEADER, type: #DATAPOINT_REFERENCE, targetQualifier: 'TotalValue', position: 10 }, { id: 'ItemCountHeader', purpose: #HEADER, type: #DATAPOINT_REFERENCE, targetQualifier: 'ItemCount', position: 20 }, { id: 'StatusHeader', purpose: #HEADER, type: #DATAPOINT_REFERENCE, targetQualifier: 'Status', position: 30 }, { id: 'TrendChart', purpose: #HEADER, type: #CHART_REFERENCE, targetQualifier: 'MonthlySales', position: 40 },
-- Sections de contenu { id: 'GeneralSection', purpose: #STANDARD, type: #COLLECTION, label: 'Général', position: 10 }, { id: 'CustomerData', purpose: #STANDARD, type: #FIELDGROUP_REFERENCE, targetQualifier: 'Customer', parentId: 'GeneralSection', label: 'Données client', position: 10 }, { id: 'OrderData', purpose: #STANDARD, type: #FIELDGROUP_REFERENCE, targetQualifier: 'Order', parentId: 'GeneralSection', label: 'Données de commande', position: 20 }, { id: 'ItemsSection', purpose: #STANDARD, type: #LINEITEM_REFERENCE, targetElement: '_Items', label: 'Positions', position: 20 }, { id: 'ShippingSection', purpose: #STANDARD, type: #FIELDGROUP_REFERENCE, targetQualifier: 'Shipping', label: 'Expédition', position: 30, hidden: 'HideShipping" } ]
@UI.lineItem: [{ position: 10 }] @UI.selectionField: [{ position: 10 }] key SalesOrderId,
@UI.lineItem: [{ position: 20 }] @UI.selectionField: [{ position: 20 }] @UI.fieldGroup: [{ qualifier: 'Customer', position: 10 }] CustomerId,
@UI.lineItem: [{ position: 30 }] @UI.fieldGroup: [{ qualifier: 'Customer', position: 20 }] CustomerName,
@UI.fieldGroup: [{ qualifier: 'Customer', position: 30 }] CustomerCity,
@UI.lineItem: [{ position: 40 }] @UI.selectionField: [{ position: 30 }] @UI.fieldGroup: [{ qualifier: 'Order', position: 10 }] OrderDate,
@UI.fieldGroup: [{ qualifier: 'Order', position: 20 }] RequestedDeliveryDate,
@UI.lineItem: [{ position: 50, criticality: 'StatusCriticality' }] @UI.selectionField: [{ position: 40 }] @UI.dataPoint: { qualifier: 'Status', title: 'Statut', criticality: 'StatusCriticality" } Status,
StatusCriticality,
@UI.lineItem: [{ position: 60 }] @UI.dataPoint: { qualifier: 'TotalValue', title: 'Valeur de commande" } @Semantics.amount.currencyCode: 'CurrencyCode" TotalValue,
CurrencyCode,
@UI.dataPoint: { qualifier: 'ItemCount', title: 'Positions" } NumberOfItems,
@UI.fieldGroup: [{ qualifier: 'Shipping', position: 10 }] TrackingNumber,
@UI.fieldGroup: [{ qualifier: 'Shipping', position: 20 }] ShippedDate,
-- Conditionnel : Expédition uniquement pour commandes expédiées case when Status in ('SHIPPED', 'DELIVERED') then abap_false else abap_true end as HideShipping,
_Items}Bonnes pratiques
1. Nommer les ID de facettes de manière cohérente
-- Bonne convention de nommage{ id: 'HeaderStatus', -- Header + Contenu id: 'SectionCustomer', -- Section + Thème id: 'FieldGroupAddress', -- Type + Contenu}2. Attribuer les positions avec des intervalles
-- Avec intervalles pour extensions ultérieuresposition: 10position: 20position: 30
-- Pas : 1, 2, 3 (pas d'intervalles pour extensions)3. Criticality toujours comme champ séparé
-- Bon : Champ séparé pour CriticalityStatus,StatusCriticality,
-- À éviter : Calcul inline dans l'annotation4. Tenir compte des performances pour les graphiques
-- Optimiser les agrégations pour les graphiques@Aggregation.default: #SUMRevenue,
-- Limiter la quantité de données pour les graphiques d'en-têteErreurs typiques et solutions
| Problème | Cause | Solution |
|---|---|---|
| Facette non affichée | purpose incorrect | Vérifier #HEADER vs. #STANDARD |
| Graphique vide | Pas d’agrégation | Ajouter @Aggregation.default |
| Conditionnel ne fonctionne pas | Champ non exposé | Inclure le champ Hidden dans Projection |
| Groupe de champs non visible | parentId manquant | Définir parentId sur Collection |
Sujets complémentaires
- SAP Fiori Elements – Bases de la génération UI
- Annotations CDS – Toutes les annotations disponibles
- Bases RAP – Bases de RESTful ABAP Programming
- Fiori Object Page – Configurer l’Object Page