Fiori Object Page Anpassungen: Sections, Field Groups und Custom Actions

kategorie
Fiori
Veröffentlicht
autor
Johannes

Die Object Page zeigt Detail-Informationen zu einem einzelnen Business-Objekt. Sie ist das Herzstück transaktionaler Fiori-Anwendungen und ermöglicht das Anzeigen, Bearbeiten und Verwalten von Daten. Über CDS-Annotations lässt sich das Layout präzise steuern – von Header-Informationen über strukturierte Sections bis hin zu eingebetteten Tabellen.

Object Page Struktur

Eine Object Page besteht aus klar definierten Bereichen:

┌─────────────────────────────────────────────────────────────┐
│ Object Page Header │
│ ┌───────────────────────┬──────────────────────────────┐ │
│ │ Object Image/ │ Header Facets │ │
│ │ Avatar │ (KPIs, Status, Ratings) │ │
│ ├───────────────────────┴──────────────────────────────┤ │
│ │ Title: Bestellung 4711 │ │
│ │ Subtitle: Kunde: Mustermann GmbH │ │
│ └──────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ [Tab 1: Allgemein] [Tab 2: Positionen] [Tab 3: Historie] │
├─────────────────────────────────────────────────────────────┤
│ Section Content │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Subsection: Basisdaten │ │
│ │ ┌─────────────────┬─────────────────┐ │ │
│ │ │ Field Group 1 │ Field Group 2 │ │ │
│ │ │ - Feld A │ - Feld D │ │ │
│ │ │ - Feld B │ - Feld E │ │ │
│ │ │ - Feld C │ - Feld F │ │ │
│ │ └─────────────────┴─────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Subsection: Positionen (Table) │ │
│ │ | Pos | Material | Menge | Preis | │ │
│ │ |-----|----------|-------|-------| │ │
│ │ | 10 | MAT-001 | 5 | 100€ | │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘

Grundlegende Object Page Konfiguration

Header Title und Subtitle

@UI.headerInfo: {
typeName: 'Bestellung',
typeNamePlural: 'Bestellungen',
title: {
type: #STANDARD,
value: 'OrderId'
},
description: {
type: #STANDARD,
value: 'CustomerName'
},
imageUrl: 'ImageUrl' -- Optional: Bild/Avatar
}
define view entity ZC_SalesOrder
as projection on ZI_SalesOrder
{
...
}

Object Page mit Facets definieren

@UI.facet: [
-- Header Facets
{
id: 'HeaderStatus',
purpose: #HEADER,
type: #DATAPOINT_REFERENCE,
targetQualifier: 'Status',
position: 10
},
{
id: 'HeaderTotal',
purpose: #HEADER,
type: #DATAPOINT_REFERENCE,
targetQualifier: 'TotalAmount',
position: 20
},
-- Content Sections
{
id: 'GeneralSection',
purpose: #STANDARD,
type: #COLLECTION,
label: 'Allgemein',
position: 10
},
{
id: 'ItemsSection',
purpose: #STANDARD,
type: #LINEITEM_REFERENCE,
label: 'Positionen',
position: 20,
targetElement: '_Items'
}
]

Multiple Sections mit Tabs

Mehrere Sections werden automatisch als Tabs dargestellt, wenn sie auf der gleichen Ebene definiert sind.

Beispiel: Drei-Tab-Layout

@UI.facet: [
-- Tab 1: Allgemein
{
id: 'GeneralTab',
purpose: #STANDARD,
type: #COLLECTION,
label: 'Allgemein',
position: 10
},
{
id: 'GeneralBasic',
parentId: 'GeneralTab',
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'BasicData',
label: 'Basisdaten',
position: 10
},
{
id: 'GeneralDates',
parentId: 'GeneralTab',
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'Dates',
label: 'Termine',
position: 20
},
-- Tab 2: Positionen
{
id: 'ItemsTab',
purpose: #STANDARD,
type: #COLLECTION,
label: 'Positionen',
position: 20
},
{
id: 'ItemsTable',
parentId: 'ItemsTab',
type: #LINEITEM_REFERENCE,
label: 'Bestellpositionen',
targetElement: '_Items',
position: 10
},
-- Tab 3: Historie
{
id: 'HistoryTab',
purpose: #STANDARD,
type: #COLLECTION,
label: 'Historie',
position: 30
},
{
id: 'ChangeLog',
parentId: 'HistoryTab',
type: #LINEITEM_REFERENCE,
label: 'Aenderungsprotokoll',
targetElement: '_ChangeLog',
position: 10
}
]

Subsections innerhalb von Tabs

Für komplexere Layouts können Tabs weitere Unterteilungen haben:

@UI.facet: [
{
id: 'GeneralTab',
purpose: #STANDARD,
type: #COLLECTION,
label: 'Allgemein',
position: 10
},
-- Subsection 1: Kopfdaten
{
id: 'HeaderData',
parentId: 'GeneralTab',
type: #COLLECTION,
label: 'Kopfdaten',
position: 10
},
{
id: 'HeaderFields',
parentId: 'HeaderData',
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'HeaderFields',
position: 10
},
-- Subsection 2: Konditionen
{
id: 'Conditions',
parentId: 'GeneralTab',
type: #COLLECTION,
label: 'Konditionen',
position: 20
},
{
id: 'ConditionFields',
parentId: 'Conditions',
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'ConditionFields',
position: 10
}
]

Field Groups und Form Layouts

Field Groups organisieren Felder in logischen Blöcken. Sie werden als Formularbereiche dargestellt.

Field Group Definition

define view entity ZC_SalesOrder
as projection on ZI_SalesOrder
{
@UI.facet: [
{
id: 'BasicDataSection',
type: #COLLECTION,
label: 'Basisdaten',
position: 10
},
{
id: 'OrderInfo',
parentId: 'BasicDataSection',
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'OrderInfo',
label: 'Bestellinformationen',
position: 10
},
{
id: 'CustomerInfo',
parentId: 'BasicDataSection',
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'CustomerInfo',
label: 'Kundeninformationen',
position: 20
}
]
@UI.fieldGroup: [{ qualifier: 'OrderInfo', position: 10 }]
@UI.identification: [{ position: 10 }]
key OrderId,
@UI.fieldGroup: [{ qualifier: 'OrderInfo', position: 20 }]
OrderDate,
@UI.fieldGroup: [{ qualifier: 'OrderInfo', position: 30 }]
Status,
@UI.fieldGroup: [{ qualifier: 'CustomerInfo', position: 10 }]
CustomerId,
@UI.fieldGroup: [{ qualifier: 'CustomerInfo', position: 20 }]
CustomerName,
@UI.fieldGroup: [{ qualifier: 'CustomerInfo', position: 30 }]
CustomerCity
}

Mehrspaltiges Layout

Field Groups werden standardmäßig nebeneinander dargestellt. Für explizite Kontrolle:

@UI.facet: [
{
id: 'TwoColumnSection',
type: #COLLECTION,
label: 'Zwei Spalten',
position: 10
},
{
id: 'LeftColumn',
parentId: 'TwoColumnSection',
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'LeftFields',
label: 'Linke Spalte',
position: 10
},
{
id: 'RightColumn',
parentId: 'TwoColumnSection',
type: #FIELDGROUP_REFERENCE,
targetQualifier: 'RightFields',
label: 'Rechte Spalte',
position: 20
}
]

Inline Tables in Object Page

Untergeordnete Entitäten können als Tabellen direkt in der Object Page angezeigt werden.

Standard LineItem Table

-- In der Root Entity
@UI.facet: [{
id: 'ItemsSection',
purpose: #STANDARD,
type: #LINEITEM_REFERENCE,
label: 'Positionen',
targetElement: '_Items',
position: 20
}]
-- In der untergeordneten Entity (Items)
define view entity ZC_SalesOrderItem
as projection on ZI_SalesOrderItem
{
@UI.lineItem: [{ position: 10 }]
key OrderId,
@UI.lineItem: [{ position: 20 }]
key ItemNumber,
@UI.lineItem: [{ position: 30 }]
MaterialNumber,
@UI.lineItem: [{ position: 40 }]
Quantity,
@UI.lineItem: [{ position: 50 }]
@Semantics.amount.currencyCode: 'Currency'
NetPrice,
@UI.lineItem: [{ position: 60 }]
Currency
}

Table mit Actions

define view entity ZC_SalesOrderItem
as projection on ZI_SalesOrderItem
{
@UI.lineItem: [
{ position: 10 },
{ type: #FOR_ACTION, dataAction: 'deleteItem', label: 'Loeschen' },
{ type: #FOR_ACTION, dataAction: 'copyItem', label: 'Kopieren' }
]
key ItemNumber,
...
}

Editierbare Inline-Tabelle

Für editierbare Tabellen muss die Behavior Definition entsprechend konfiguriert sein:

define behavior for ZI_SalesOrder alias SalesOrder
{
...
association _Items { create; }
}
define behavior for ZI_SalesOrderItem alias SalesOrderItem
{
update;
delete;
field ( readonly ) OrderId, ItemNumber;
field ( mandatory ) MaterialNumber, Quantity;
}

Custom Actions auf Object Page

Actions können im Header, in Sections oder auf Feldebene platziert werden.

Header Actions

@UI.identification: [
{ position: 10 },
{ type: #FOR_ACTION, dataAction: 'approve', label: 'Genehmigen' },
{ type: #FOR_ACTION, dataAction: 'reject', label: 'Ablehnen' },
{ type: #FOR_ACTION, dataAction: 'sendEmail', label: 'E-Mail senden' }
]
key OrderId,

Actions mit Criticality (Farbcodierung)

@UI.identification: [{
type: #FOR_ACTION,
dataAction: 'approve',
label: 'Genehmigen',
criticality: 'ApproveCriticality' -- Dynamische Kritikalitaet
}]
key OrderId,
-- Berechnetes Feld fuer Criticality
@UI.hidden: true
cast( case Status
when 'OPEN' then 3 -- Gruen
when 'PENDING' then 2 -- Gelb
else 0
end as abap.int1 ) as ApproveCriticality,

Conditional Actions (Feature Control)

Actions können basierend auf Daten ein-/ausgeblendet werden:

-- In der Behavior Definition
define behavior for ZI_SalesOrder alias SalesOrder
{
action approve result [1] $self;
// Feature Control
determination setFeatures on modify { field Status; }
}
-- In der Behavior Implementation
METHOD get_instance_features.
READ ENTITIES OF zi_salesorder IN LOCAL MODE
ENTITY SalesOrder
FIELDS ( Status )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_orders).
LOOP AT lt_orders INTO DATA(ls_order).
APPEND VALUE #(
%tky = ls_order-%tky
%action-approve = COND #(
WHEN ls_order-Status = 'OPEN'
THEN if_abap_behv=>fc-o-enabled
ELSE if_abap_behv=>fc-o-disabled
)
) TO result.
ENDLOOP.
ENDMETHOD.

Actions in Sections

@UI.facet: [{
id: 'AdminSection',
purpose: #STANDARD,
type: #COLLECTION,
label: 'Administration',
position: 40
}]
-- Feldgruppe mit Actions
@UI.fieldGroup: [{
qualifier: 'AdminActions',
position: 10,
type: #FOR_ACTION,
dataAction: 'archive',
label: 'Archivieren'
}]

Responsive Layout-Anpassungen

Fiori Elements passt das Layout automatisch an verschiedene Bildschirmgrößen an. Zusätzliche Kontrolle ist möglich.

Importance für responsive Anpassung

@UI.lineItem: [{
position: 10,
importance: #HIGH -- Immer sichtbar
}]
OrderId,
@UI.lineItem: [{
position: 20,
importance: #MEDIUM -- Ausgeblendet auf kleinen Screens
}]
OrderDate,
@UI.lineItem: [{
position: 30,
importance: #LOW -- Nur auf grossen Screens
}]
CreatedBy,

Hidden Fields

Felder können komplett ausgeblendet werden:

@UI.hidden: true
InternalField,
-- Oder dynamisch
@UI.hidden: #( HideCondition )
ConditionalField,

FieldGroup Column Layout

@UI.fieldGroup: [{
qualifier: 'Details',
position: 10,
label: 'Bestellnummer'
}]
@EndUserText.label: 'Bestellnummer'
OrderId,

Header Facets konfigurieren

DataPoint im Header

@UI.facet: [{
id: 'HeaderStatus',
purpose: #HEADER,
type: #DATAPOINT_REFERENCE,
targetQualifier: 'StatusDP',
position: 10
}]
@UI.dataPoint: {
qualifier: 'StatusDP',
title: 'Status',
criticality: 'StatusCriticality'
}
Status,

Progress Indicator

@UI.dataPoint: {
qualifier: 'Completion',
title: 'Fertigstellung',
visualization: #PROGRESS,
targetValue: 100
}
CompletionPercent,

Rating Indicator

@UI.dataPoint: {
qualifier: 'CustomerRating',
title: 'Kundenbewertung',
visualization: #RATING,
targetValue: 5
}
Rating,

Contact Card im Header

@UI.facet: [{
id: 'ContactCard',
purpose: #HEADER,
type: #CONTACT_REFERENCE,
targetElement: '_Contact',
position: 30
}]

Vollständiges Beispiel

@EndUserText.label: 'Sales Order - Projection'
@Metadata.allowExtensions: true
@UI.headerInfo: {
typeName: 'Bestellung',
typeNamePlural: 'Bestellungen',
title: { type: #STANDARD, value: 'OrderId' },
description: { type: #STANDARD, value: 'CustomerName' }
}
define view entity ZC_SalesOrder
as projection on ZI_SalesOrder
{
@UI.facet: [
-- Header Facets
{ id: 'HeaderStatus', purpose: #HEADER, type: #DATAPOINT_REFERENCE,
targetQualifier: 'Status', position: 10 },
{ id: 'HeaderTotal', purpose: #HEADER, type: #DATAPOINT_REFERENCE,
targetQualifier: 'TotalAmount', position: 20 },
-- Tab 1: Allgemein
{ id: 'GeneralTab', purpose: #STANDARD, type: #COLLECTION,
label: 'Allgemein', position: 10 },
{ id: 'OrderData', parentId: 'GeneralTab',
type: #FIELDGROUP_REFERENCE, targetQualifier: 'OrderData',
label: 'Bestelldaten', position: 10 },
{ id: 'CustomerData', parentId: 'GeneralTab',
type: #FIELDGROUP_REFERENCE, targetQualifier: 'CustomerData',
label: 'Kundendaten', position: 20 },
-- Tab 2: Positionen
{ id: 'ItemsTab', purpose: #STANDARD, type: #COLLECTION,
label: 'Positionen', position: 20 },
{ id: 'ItemsTable', parentId: 'ItemsTab',
type: #LINEITEM_REFERENCE, targetElement: '_Items',
label: 'Bestellpositionen', position: 10 },
-- Tab 3: Notizen
{ id: 'NotesTab', purpose: #STANDARD, type: #COLLECTION,
label: 'Notizen', position: 30 },
{ id: 'NotesField', parentId: 'NotesTab',
type: #FIELDGROUP_REFERENCE, targetQualifier: 'Notes',
position: 10 }
]
@UI.identification: [
{ position: 10 },
{ type: #FOR_ACTION, dataAction: 'approve', label: 'Genehmigen' },
{ type: #FOR_ACTION, dataAction: 'reject', label: 'Ablehnen' }
]
@UI.fieldGroup: [{ qualifier: 'OrderData', position: 10 }]
key OrderId,
@UI.dataPoint: { qualifier: 'Status', title: 'Status',
criticality: 'StatusCriticality' }
@UI.fieldGroup: [{ qualifier: 'OrderData', position: 20 }]
Status,
@UI.hidden: true
StatusCriticality,
@UI.fieldGroup: [{ qualifier: 'OrderData', position: 30 }]
OrderDate,
@UI.dataPoint: { qualifier: 'TotalAmount', title: 'Gesamtbetrag' }
@UI.fieldGroup: [{ qualifier: 'OrderData', position: 40 }]
@Semantics.amount.currencyCode: 'Currency'
TotalAmount,
Currency,
@UI.fieldGroup: [{ qualifier: 'CustomerData', position: 10 }]
CustomerId,
@UI.fieldGroup: [{ qualifier: 'CustomerData', position: 20 }]
CustomerName,
@UI.fieldGroup: [{ qualifier: 'CustomerData', position: 30 }]
CustomerCity,
@UI.fieldGroup: [{ qualifier: 'Notes', position: 10 }]
@UI.multiLineText: true
Notes,
-- Assoziationen
_Items : redirected to composition child ZC_SalesOrderItem
}

Best Practices

AspektEmpfehlung
Tab-AnzahlMaximal 5-7 Tabs fuer Uebersichtlichkeit
Field GroupsLogische Gruppierung, max. 6-8 Felder pro Gruppe
Header FacetsNur wichtigste KPIs, max. 4-5 Facets
ActionsPrimaere Aktionen prominent, sekundaere in Menue
Inline TablesPagination aktivieren bei grossen Datenmengen

Zusammenfassung

Die Object Page bietet umfangreiche Anpassungsmöglichkeiten über CDS-Annotations:

  • Header: Title, Subtitle, DataPoints, Contact Cards
  • Sections/Tabs: Strukturierte Inhaltsorganisation mit #COLLECTION
  • Field Groups: Formularlayout mit #FIELDGROUP_REFERENCE
  • Inline Tables: Untergeordnete Entitäten mit #LINEITEM_REFERENCE
  • Actions: Header-Actions, Section-Actions, Table-Actions
  • Responsive: importance für adaptive Layouts

Die Kombination dieser Elemente ermöglicht professionelle Detail-Ansichten ohne UI5-Code.

Verwandte Themen