Fiori List Report Anpassungen: Header Facets, Sections und Charts

kategorie
Fiori
Veröffentlicht
autor
Johannes

Der List Report ist eine der meistgenutzten Fiori Elements Templates. Er zeigt Daten tabellarisch an und bietet Filter, Sortierung und Aktionen. Über CDS-Annotations kannst du das Erscheinungsbild detailliert anpassen – ohne eine Zeile UI5-Code.

Grundstruktur eines List Reports

Ein List Report besteht aus mehreren Bereichen:

┌─────────────────────────────────────────────────────────┐
│ Header Area │
│ ┌───────────────────────────────────────────────────┐ │
│ │ Header Facets (KPIs, Charts, Status) │ │
│ └───────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────┤
│ Filter Bar │
│ [Field 1 ▼] [Field 2 ▼] [Field 3 ▼] [Go] [Adapt] │
├─────────────────────────────────────────────────────────┤
│ Table Toolbar │
│ [Create] [Delete] [Custom Action] │
├─────────────────────────────────────────────────────────┤
│ Table Content │
│ | Col 1 | Col 2 | Col 3 | Col 4 | │
│ |-------|-------|-------|-------| │
│ | Row 1 | ... | ... | ... | │
│ | Row 2 | ... | ... | ... | │
└─────────────────────────────────────────────────────────┘

@UI.facet Annotation im Detail

Die @UI.facet Annotation ist der Schlüssel zur Anpassung von List Reports und Object Pages. Sie definiert, welche Facets (Abschnitte) angezeigt werden und wie sie strukturiert sind.

Facet-Typen

TypBeschreibungVerwendung
#HEADER_SECTIONBereich im HeaderKPIs, Status-Indikatoren
#COLLECTIONContainer für mehrere FacetsGruppierung
#IDENTIFICATION_REFERENCEStandard-IdentifikationsfelderObject Page Header
#LINEITEM_REFERENCETabellenansichtUntergeordnete Entitäten
#DATAPOINT_REFERENCEEinzelner DatenpunktKPI, Kennzahl
#CHART_REFERENCEDiagrammVisualisierungen
#FIELDGROUP_REFERENCEFeldgruppeFormularbereiche

Grundstruktur einer Facet-Definition

@UI.facet: [{
id: 'HeaderFacetID', -- Eindeutige ID
purpose: #HEADER, -- #HEADER oder #STANDARD
type: #DATAPOINT_REFERENCE, -- Facet-Typ
targetQualifier: 'TotalAmount', -- Referenz auf @UI.dataPoint
label: 'Gesamtbetrag', -- Anzeigetext
position: 10 -- Reihenfolge
}]

Header und Collection Facets: Der Unterschied

Header Facets erscheinen im oberen Bereich (Header) eines List Reports oder einer Object Page. Sie zeigen verdichtete Informationen wie KPIs oder Status.

Collection Facets sind Container, die mehrere Facets gruppieren. Sie erscheinen typischerweise im Content-Bereich der Object Page.

@UI.facet: [
-- Header Facets (oben im Header)
{
id: 'HeaderKPI',
purpose: #HEADER, -- Header-Bereich
type: #DATAPOINT_REFERENCE,
targetQualifier: 'TotalOrders',
position: 10
},
-- Collection Facet (Content-Bereich)
{
id: 'GeneralInfo',
purpose: #STANDARD, -- Content-Bereich
type: #COLLECTION, -- Container
label: 'Allgemeine Informationen',
position: 20
},
{
id: 'Details',
purpose: #STANDARD,
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'Details',
parentId: 'GeneralInfo', -- Untergeordnet
position: 10
}
]

Custom Header Facets (KPIs, Status-Indikatoren)

Header Facets eignen sich perfekt für KPIs und Statusanzeigen.

KPI mit DataPoint

@Metadata.allowExtensions: true
define view entity ZC_SalesOrder
as projection on ZI_SalesOrder
{
key SalesOrderId,
@UI.dataPoint: {
qualifier: 'TotalAmount',
title: 'Bestellwert',
valueFormat: { numberOfFractionalDigits: 2 }
}
@Semantics.amount.currencyCode: 'CurrencyCode'
TotalAmount,
CurrencyCode,
@UI.dataPoint: {
qualifier: 'ItemCount',
title: 'Positionen',
valueFormat: { numberOfFractionalDigits: 0 }
}
NumberOfItems,
@UI.dataPoint: {
qualifier: 'OrderStatus',
title: 'Status',
criticality: 'StatusCriticality'
}
Status,
StatusCriticality
}

Die zugehörige Facet-Definition:

@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
}
]

Status mit Criticality

Die Criticality bestimmt die Farbe des Status-Indikators:

WertBedeutungFarbe
0NeutralGrau
1NegativRot
2KritischOrange
3PositivGrün
define view entity ZC_Order
as projection on ZI_Order
{
key OrderId,
Status,
-- Berechnung der Criticality
case Status
when 'OPEN' then 0 -- Grau
when 'PENDING' then 2 -- Orange
when 'COMPLETED' then 3 -- Grün
when 'CANCELLED' then 1 -- Rot
else 0
end as StatusCriticality
}

Custom Sections im List Report

Sections strukturieren den Content-Bereich. Mit #COLLECTION erstellst du gruppierte Abschnitte.

Mehrere Sections mit Feldgruppen

@UI.facet: [
-- Section 1: Bestellkopf
{
id: 'OrderHeader',
purpose: #STANDARD,
type: #COLLECTION,
label: 'Bestellkopf',
position: 10
},
{
id: 'BasicData',
purpose: #STANDARD,
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'BasicData',
parentId: 'OrderHeader',
label: 'Stammdaten',
position: 10
},
{
id: 'Dates',
purpose: #STANDARD,
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'Dates',
parentId: 'OrderHeader',
label: 'Termine',
position: 20
},
-- Section 2: Positionen
{
id: 'OrderItems',
purpose: #STANDARD,
type: #LINEITEM_REFERENCE,
targetElement: '_Items',
label: 'Positionen',
position: 20
},
-- Section 3: Notizen
{
id: 'Notes',
purpose: #STANDARD,
type: #COLLECTION,
label: 'Notizen & Anhänge',
position: 30
}
]

Feldgruppen definieren

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 (Datenabhängig)

Conditional Facets werden nur angezeigt, wenn bestimmte Bedingungen erfüllt sind. Dies geschieht über die hidden Eigenschaft.

Facet basierend auf Status ausblenden

@UI.facet: [
{
id: 'ShippingInfo',
purpose: #STANDARD,
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'Shipping',
label: 'Versandinformationen',
position: 20,
hidden: 'HideShipping' -- Referenz auf berechnetes Feld
}
]
define view entity ZC_Order
{
key OrderId,
Status,
-- Versandinfo nur bei bestimmten Status anzeigen
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
}

Mehrere Bedingungen kombinieren

define view entity ZC_Contract
{
key ContractId,
ContractType,
Status,
-- Facet nur für aktive Serviceverträge
case when ContractType = 'SERVICE'
and Status = 'ACTIVE'
then abap_false
else abap_true
end as HideServiceDetails,
-- Facet nur für Verträge mit Verlängerungsoption
case when HasRenewalOption = abap_true
then abap_false
else abap_true
end as HideRenewalInfo
}

Chart Integration im Header

Charts im Header visualisieren Daten auf einen Blick.

Micro Chart im Header

@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: 'Monatsumsatz',
measures: ['Revenue'],
dimensions: ['Month']
}]
@Aggregation.default: #SUM
Revenue,
Month
}

Verschiedene Chart-Typen

-- Bullet Chart für Zielerreichung
@UI.chart: [{
qualifier: 'TargetAchievement',
chartType: #BULLET,
title: 'Zielerreichung',
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 für Prozentanzeige
@UI.chart: [{
qualifier: 'CompletionRate',
chartType: #DONUT,
title: 'Fertigstellungsgrad',
measures: ['CompletedPercent']
}]
CompletedPercent

Chart mit Criticality-Farben

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,
-- Criticality berechnen
case
when SpentBudget <= TotalBudget * 0.8 then 3 -- Grün
when SpentBudget <= TotalBudget then 2 -- Orange
else 1 -- Rot
end as BudgetCriticality
}

Vollständiges Beispiel: Verkaufsübersicht

@Metadata.allowExtensions: true
@UI.headerInfo: {
typeName: 'Verkaufsbeleg',
typeNamePlural: 'Verkaufsbelege',
title: { value: 'SalesOrderId' },
description: { value: 'CustomerName' }
}
define view entity ZC_SalesOrderReport
as projection on ZI_SalesOrder
{
-- Facet-Definitionen
@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
},
-- Content Sections
{
id: 'GeneralSection',
purpose: #STANDARD,
type: #COLLECTION,
label: 'Allgemein',
position: 10
},
{
id: 'CustomerData',
purpose: #STANDARD,
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'Customer',
parentId: 'GeneralSection',
label: 'Kundendaten',
position: 10
},
{
id: 'OrderData',
purpose: #STANDARD,
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'Order',
parentId: 'GeneralSection',
label: 'Bestelldaten',
position: 20
},
{
id: 'ItemsSection',
purpose: #STANDARD,
type: #LINEITEM_REFERENCE,
targetElement: '_Items',
label: 'Positionen',
position: 20
},
{
id: 'ShippingSection',
purpose: #STANDARD,
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'Shipping',
label: 'Versand',
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: 'Status',
criticality: 'StatusCriticality'
}
Status,
StatusCriticality,
@UI.lineItem: [{ position: 60 }]
@UI.dataPoint: {
qualifier: 'TotalValue',
title: 'Bestellwert'
}
@Semantics.amount.currencyCode: 'CurrencyCode'
TotalValue,
CurrencyCode,
@UI.dataPoint: {
qualifier: 'ItemCount',
title: 'Positionen'
}
NumberOfItems,
@UI.fieldGroup: [{ qualifier: 'Shipping', position: 10 }]
TrackingNumber,
@UI.fieldGroup: [{ qualifier: 'Shipping', position: 20 }]
ShippedDate,
-- Conditional: Versand nur bei versendeten Aufträgen
case when Status in ('SHIPPED', 'DELIVERED')
then abap_false
else abap_true
end as HideShipping,
_Items
}

Best Practices

1. Facet-IDs konsistent benennen

-- Gute Namenskonvention
{
id: 'HeaderStatus', -- Header + Inhalt
id: 'SectionCustomer', -- Section + Thema
id: 'FieldGroupAddress', -- Typ + Inhalt
}

2. Positionen mit Lücken vergeben

-- Mit Lücken für spätere Erweiterungen
position: 10
position: 20
position: 30
-- Nicht: 1, 2, 3 (keine Lücken für Erweiterungen)

3. Criticality immer als separates Feld

-- Gut: Separates Feld für Criticality
Status,
StatusCriticality,
-- Vermeiden: Inline-Berechnung in Annotation

4. Performance bei Charts beachten

-- Aggregationen für Charts optimieren
@Aggregation.default: #SUM
Revenue,
-- Datenmenge begrenzen für Header Charts

Typische Fehler und Lösungen

ProblemUrsacheLösung
Facet wird nicht angezeigtpurpose falsch#HEADER vs. #STANDARD prüfen
Chart leerKeine Aggregation@Aggregation.default hinzufügen
Conditional funktioniert nichtFeld nicht exponiertHidden-Feld in Projection aufnehmen
Feldgruppe nicht sichtbarparentId fehltparentId auf Collection setzen

Weiterführende Themen