Fiori Launchpad Tiles sind der Einstiegspunkt fuer deine Anwendungen. Neben einfachen statischen Kacheln kannst du Dynamic Tiles mit Live-Daten erstellen, die Kennzahlen direkt auf dem Launchpad anzeigen. Dieser Artikel zeigt alle Tile-Typen und ihre Implementierung in ABAP Cloud.
Tile-Typen im Ueberblick
Das Fiori Launchpad unterstuetzt verschiedene Kachel-Typen:
| Tile-Typ | Beschreibung | Datenquelle |
|---|---|---|
| Static Tile | Fester Titel und Icon | Keine |
| Dynamic Tile | Live-Kennzahl mit Trend | OData Service |
| News Tile | News-Feed mit Bildern | OData Service |
| Custom Tile | Freie UI5-Implementierung | Beliebig |
| KPI Tile | Smart Business KPI | KPI Framework |
Static Tiles
Static Tiles sind die einfachste Form - ein Icon, Titel und optionaler Untertitel.
Wann verwenden?
- Einfache App-Navigation ohne Live-Daten
- Konfigurationsanwendungen
- Dokumentation und Hilfe-Links
Target Mapping Konfiguration
Die Tile-Konfiguration erfolgt ueber das Target Mapping im Fiori Launchpad Designer oder ueber den SAP Fiori Launchpad Content Manager.
Semantic Object: TravelAction: manageTile: - Title: Reisen verwalten - Subtitle: Travel Management - Icon: sap-icon://flight - Info: TransaktionalInbound Navigation in der App
In der UI5-App (manifest.json) definierst du den Inbound:
{ "sap.app": { "id": "ztravel.manage", "crossNavigation": { "inbounds": { "Travel-manage": { "semanticObject": "Travel", "action": "manage", "title": "{{appTitle}}", "subTitle": "{{appSubTitle}}", "icon": "sap-icon://flight", "signature": { "parameters": {}, "additionalParameters": "allowed" } } } } }}Dynamic Tiles - Live-Daten anzeigen
Dynamic Tiles zeigen aktuelle Kennzahlen direkt auf dem Launchpad. Die Daten werden ueber einen OData-Service geladen.
Architektur
┌─────────────────────────────────────────────────────────────────────┐│ Fiori Launchpad ││ ││ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ ││ │ Dynamic Tile │ │ Dynamic Tile │ │ Static Tile │ ││ │ │ │ │ │ │ ││ │ 42 │ │ € 125k │ │ ┌────────┐ │ ││ │ Offene Tasks │ │ Umsatz Q1 │ │ │ Icon │ │ ││ │ ↑ +5 │ │ ↓ -3% │ │ └────────┘ │ ││ └────────┬─────────┘ └────────┬─────────┘ └──────────────────┘ ││ │ │ ││ ▼ ▼ ││ OData Request OData Request ││ │ │ │└───────────┼─────────────────────┼────────────────────────────────────┘ │ │ ▼ ▼ ┌─────────────┐ ┌─────────────┐ │ CDS View │ │ CDS View │ │ ZI_TaskKPI │ │ ZI_SalesKPI │ └─────────────┘ └─────────────┘CDS View fuer Dynamic Tile
Die Basis ist ein CDS View mit einer einzigen Entity, die die Tile-Daten liefert:
@EndUserText.label: 'Open Tasks KPI for Tile'@ObjectModel.representativeKey: 'TileId'@ObjectModel.semanticKey: ['TileId']define view entity ZI_OpenTasksKPI as select from ztasks{ -- Dummy-Schluessel (nur ein Datensatz) key 1 as TileId,
-- Anzahl offene Tasks @EndUserText.label: 'Offene Tasks' cast( count(*) as abap.int4 ) as Number,
-- Einheit (optional) @EndUserText.label: 'Einheit' cast( 'Tasks' as abap.char(10) ) as NumberUnit,
-- Status-Info @EndUserText.label: 'Info' cast( 'Aktuell' as abap.char(20) ) as Info,
-- Trend: Vergleich zu gestern @EndUserText.label: 'Trend' case when count(*) > ( select count(*) from ztasks as t2 where t2.created_at < @( cl_abap_context_info=>get_system_date( ) ) and t2.status = 'O' ) then cast( 'Up' as abap.char(10) ) else cast( 'Down' as abap.char(10) ) end as NumberTrend,
-- Trend-Pfeil (1=up, 0=none, -1=down) @EndUserText.label: 'State Arrow' case when count(*) > ( select count(*) from ztasks as t2 where t2.created_at < @( cl_abap_context_info=>get_system_date( ) ) and t2.status = 'O' ) then 1 else -1 end as StateArrow
}where status = 'O' -- Nur offene Tasksgroup by statusVereinfachte Version mit Custom Entity
Fuer komplexere Berechnungen verwende eine Custom Entity:
@EndUserText.label: 'Sales KPI for Dynamic Tile'@ObjectModel.query.implementedBy: 'ABAP:ZCL_SALES_KPI_QUERY'define custom entity ZC_SalesKPI{ key TileId : abap.int4; Number : abap.dec(15,2); NumberUnit : abap.char(10); NumberFactor : abap.char(10); NumberDigits : abap.int4; NumberState : abap.char(20); StateArrow : abap.int1; Info : abap.char(30); InfoState : abap.char(20); TargetNumber : abap.dec(15,2); Subtitle : abap.char(50);}Query-Implementierung
CLASS zcl_sales_kpi_query DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. INTERFACES if_rap_query_provider.ENDCLASS.
CLASS zcl_sales_kpi_query IMPLEMENTATION. METHOD if_rap_query_provider~select.
" Umsatz berechnen SELECT SUM( amount ) AS total_sales FROM zsales WHERE fiscal_year = @( substring( cl_abap_context_info=>get_system_date( ), 1, 4 ) ) INTO @DATA(lv_current_sales).
" Vorjahresumsatz SELECT SUM( amount ) AS total_sales FROM zsales WHERE fiscal_year = @( substring( cl_abap_context_info=>get_system_date( ), 1, 4 ) - 1 ) INTO @DATA(lv_last_year_sales).
" Trend berechnen DATA(lv_trend) = COND i( WHEN lv_current_sales > lv_last_year_sales THEN 1 WHEN lv_current_sales < lv_last_year_sales THEN -1 ELSE 0 ).
" Prozentuale Aenderung DATA(lv_change_pct) = COND decfloat34( WHEN lv_last_year_sales > 0 THEN ( lv_current_sales - lv_last_year_sales ) / lv_last_year_sales * 100 ELSE 0 ).
" Status ermitteln DATA(lv_state) = COND string( WHEN lv_change_pct >= 5 THEN 'Good' WHEN lv_change_pct >= 0 THEN 'Neutral' ELSE 'Critical' ).
" Ergebnis aufbereiten DATA(lt_result) = VALUE ztt_sales_kpi( ( TileId = 1 Number = lv_current_sales / 1000 " In Tausend NumberUnit = 'EUR' NumberFactor = 'k' NumberDigits = 1 NumberState = lv_state StateArrow = lv_trend Info = |{ lv_change_pct DECIMALS = 1 }% vs. Vorjahr| InfoState = lv_state TargetNumber = lv_last_year_sales * '1.05' Subtitle = |Stand: { cl_abap_context_info=>get_system_date( ) DATE = USER }| ) ).
io_response->set_data( lt_result ). io_response->set_total_number_of_records( 1 ).
ENDMETHOD.ENDCLASS.Service Binding fuer Dynamic Tile
@EndUserText.label: 'KPI Tiles Service'define service ZSB_KPI_TILES { expose ZI_OpenTasksKPI; expose ZC_SalesKPI;}Target Mapping mit dynamischer Kachel
Im Launchpad Content Manager oder Designer:
Semantic Object: TaskAction: manageTile Configuration: - Tile Type: Dynamic - Title: Offene Tasks - Subtitle: Task Management - Icon: sap-icon://task - Service URL: /sap/opu/odata4/sap/zsb_kpi_tiles/srvd/sap/zsb_kpi_tiles/0001/ - Entity Set: ZI_OpenTasksKPI - Number: Number - Number Unit: NumberUnit - Number State: NumberState - State Arrow: StateArrow - Info: InfoDynamic Tile Felder
| Feld | Beschreibung | Beispiel |
|---|---|---|
Number | Hauptkennzahl | 42 |
NumberUnit | Einheit | ”EUR”, “Tasks” |
NumberFactor | Skalierung | ”k”, “M”, “B” |
NumberDigits | Dezimalstellen | 0, 1, 2 |
NumberState | Farbe | ”Good”, “Critical”, “Neutral” |
StateArrow | Trendpfeil | 1=up, 0=none, -1=down |
Info | Zusatzinfo | ”+5% vs. Vorjahr” |
InfoState | Info-Farbe | ”Good”, “Critical” |
News Tiles
News Tiles zeigen einen Feed mit Bildern und Beschreibungen.
CDS View fuer News Tile
@EndUserText.label: 'Company News for Tile'@ObjectModel.semanticKey: ['NewsId']define view entity ZI_CompanyNews as select from znews{ key news_id as NewsId,
@EndUserText.label: 'Titel' title as Title,
@EndUserText.label: 'Beschreibung' description as Description,
@EndUserText.label: 'Bild-URL' image_url as ImageUrl,
@EndUserText.label: 'Link' link_url as LinkUrl,
@EndUserText.label: 'Datum' published_at as PublishedAt}where published_at <= $session.system_dateorder by published_at descendingNews Feed Konfiguration
{ "tileType": "sap.ushell.ui.tile.DynamicTile", "tileConfiguration": { "semantic_object": "News", "semantic_action": "display", "service_url": "/sap/opu/odata4/sap/zsb_news/srvd/sap/zsb_news/0001/", "service_refresh_interval": 300, "collection": "ZI_CompanyNews", "title": "{Title}", "subtitle": "{Description}", "imageUrl": "{ImageUrl}", "targetURL": "{LinkUrl}" }}Target Mapping - Navigation konfigurieren
Das Target Mapping verbindet die Kachel mit der Zielanwendung.
Konzept
┌─────────────────────────────────────────────────────────────────────┐│ Target Mapping │├─────────────────────────────────────────────────────────────────────┤│ ││ Semantic Object: "SalesOrder" ││ Action: "manage" ││ ││ ┌─────────────────────────────────────────────────────────────┐ ││ │ Tile (Was der User sieht) │ ││ │ - Title: "Auftraege verwalten" │ ││ │ - Icon: sap-icon://sales-order │ ││ │ - Dynamic Data: OData Service │ ││ └─────────────────────────────────────────────────────────────┘ ││ │ ││ ▼ ││ ┌─────────────────────────────────────────────────────────────┐ ││ │ Target (Wohin navigiert wird) │ ││ │ - Application Type: SAPUI5 Fiori App │ ││ │ - URL: /sap/bc/ui5_ui5/sap/zsalesorder_app │ ││ │ - Parameters: SalesOrg=1000 │ ││ └─────────────────────────────────────────────────────────────┘ ││ │└─────────────────────────────────────────────────────────────────────┘Launchpad Content Manager
In ABAP Cloud erfolgt die Konfiguration ueber den SAP Fiori Launchpad Content Manager:
- Apps anlegen (Service Binding verknuepfen)
- Catalogs erstellen (Apps gruppieren)
- Groups definieren (Sichtbare Gruppen im Launchpad)
- Roles zuweisen (Wer sieht was)
Programmatische Konfiguration
Fuer automatisiertes Deployment kannst du die Konfiguration als JSON exportieren:
{ "apps": [ { "id": "ztravel_manage", "vizId": "Travel-manage", "vizType": "sap.ushell.StaticAppLauncher", "title": "Reisen verwalten", "subTitle": "Travel Management", "icon": "sap-icon://flight", "info": "Travel", "target": { "type": "URL", "url": "/sap/bc/ui5_ui5/sap/ztravel_manage/index.html" } } ], "catalogs": [ { "id": "ZTRAVEL_CATALOG", "title": "Travel Management", "apps": ["ztravel_manage", "ztravel_approve"] } ], "groups": [ { "id": "ZTRAVEL_GROUP", "title": "Reisemanagement", "apps": ["ztravel_manage"] } ]}Dynamic Tile mit Live-Daten - Vollstaendiges Beispiel
Schritt 1: Datenbank-Tabelle
@EndUserText.label: 'Purchase Orders'@AbapCatalog.enhancement.category: #NOT_EXTENSIBLEdefine table zpurchase_orders { key client : abap.clnt; key po_id : abap.numc(10); vendor_id : abap.numc(10); amount : abap.curr(15,2); currency : abap.cuky; status : abap.char(1); -- O=Open, A=Approved, R=Rejected created_at : timestampl; created_by : abap.uname;}Schritt 2: KPI CDS View
@EndUserText.label: 'Open PO KPI for Dynamic Tile'@ObjectModel.query.implementedBy: 'ABAP:ZCL_OPEN_PO_KPI'define custom entity ZC_OpenPurchaseOrdersKPI{ key TileId : abap.int4; Number : abap.int4; NumberUnit : abap.char(10); NumberState : abap.char(20); StateArrow : abap.int1; Info : abap.char(50); InfoState : abap.char(20); Subtitle : abap.char(50);}Schritt 3: Query-Implementierung
CLASS zcl_open_po_kpi DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. INTERFACES if_rap_query_provider.ENDCLASS.
CLASS zcl_open_po_kpi IMPLEMENTATION. METHOD if_rap_query_provider~select.
DATA: lv_today TYPE d, lv_yesterday TYPE d.
lv_today = cl_abap_context_info=>get_system_date( ). lv_yesterday = lv_today - 1.
" Offene POs heute SELECT COUNT(*) FROM zpurchase_orders WHERE status = 'O' INTO @DATA(lv_open_today).
" Offene POs gestern (Snapshot) SELECT COUNT(*) FROM zpurchase_orders WHERE status = 'O' AND created_at < @( CONV timestampl( lv_today ) ) INTO @DATA(lv_open_yesterday).
" Differenz DATA(lv_diff) = lv_open_today - lv_open_yesterday.
" Trend bestimmen DATA(lv_arrow) = COND i( WHEN lv_diff > 0 THEN 1 " Mehr offene POs = schlecht WHEN lv_diff < 0 THEN -1 " Weniger = gut ELSE 0 ).
" Status (umgekehrte Logik: weniger offen = gut) DATA(lv_state) = COND string( WHEN lv_diff <= 0 THEN 'Good' WHEN lv_diff <= 5 THEN 'Neutral' ELSE 'Critical' ).
" Info-Text DATA(lv_info) = COND string( WHEN lv_diff > 0 THEN |+{ lv_diff } seit gestern| WHEN lv_diff < 0 THEN |{ lv_diff } seit gestern| ELSE |Unveraendert| ).
" Ergebnis DATA(lt_result) = VALUE ztt_open_po_kpi( ( TileId = 1 Number = lv_open_today NumberUnit = 'POs' NumberState = lv_state StateArrow = lv_arrow Info = lv_info InfoState = lv_state Subtitle = |Offene Bestellungen| ) ).
io_response->set_data( lt_result ). io_response->set_total_number_of_records( 1 ).
ENDMETHOD.ENDCLASS.Schritt 4: Service Definition
@EndUserText.label: 'Purchase Order KPI Service'define service ZSB_PO_KPI { expose ZC_OpenPurchaseOrdersKPI;}Schritt 5: Service Binding erstellen
In ADT:
- Rechtsklick auf Service Definition → New Service Binding
- Binding Type: OData V4 - UI
- Aktivieren und URL testen
Schritt 6: Launchpad Konfiguration
Im Launchpad Content Manager die Kachel konfigurieren:
| Parameter | Wert |
|---|---|
| Tile Type | Dynamic |
| Service URL | /sap/opu/odata4/sap/zsb_po_kpi/srvd/sap/zsb_po_kpi/0001/ |
| Entity Set | ZC_OpenPurchaseOrdersKPI |
| Number Property | Number |
| Number Unit | NumberUnit |
| Number State | NumberState |
| State Arrow | StateArrow |
| Info | Info |
| Refresh Interval | 30 (Sekunden) |
Refresh-Intervall und Performance
Empfehlungen
| Anwendungsfall | Refresh-Intervall |
|---|---|
| Echtzeit-Kennzahlen | 10-30 Sekunden |
| Standard-KPIs | 60-300 Sekunden |
| Tageswerte | 900+ Sekunden |
| Statische Daten | Manuell |
Performance-Optimierung
METHOD if_rap_query_provider~select. " Caching fuer aufwaendige Berechnungen DATA: lv_cache_key TYPE string, ls_cached TYPE zs_kpi_cache.
lv_cache_key = |PO_KPI_{ sy-datum }|.
" Cache pruefen (z.B. Shared Memory oder Application Buffer) IF cache_is_valid( lv_cache_key ). ls_cached = get_from_cache( lv_cache_key ). ELSE. " Berechnung durchfuehren ls_cached = calculate_kpi( ). put_to_cache( lv_cache_key, ls_cached ). ENDIF.
io_response->set_data( VALUE #( ( ls_cached ) ) ).ENDMETHOD.IAM und Berechtigungen
Die Sichtbarkeit von Tiles wird ueber IAM Business Catalogs gesteuert:
IAM Business Catalog: ZPO_BC_BUYER├── IAM App: ZPO_MANAGE (Bestellungen verwalten)├── IAM App: ZPO_KPI (KPI Tile Service)└── Restriction Type: ZPO_RT (Org-Einheiten)Ohne Zuweisung des Business Catalogs zur Business Role ist die Kachel nicht sichtbar.
Catalog fuer KPI-Services
<?xml version="1.0" encoding="utf-8"?><iam:catalog xmlns:iam="http://www.sap.com/iam" catalogId="ZPO_BC_KPI">
<catalogDescription>Purchase Order KPI Tiles</catalogDescription>
<catalogApps> <iamApp>ZPO_KPI_TILES</iamApp> </catalogApps>
</iam:catalog>Best Practices
1. Semantische Objekte konsistent benennen
Semantic Object: PurchaseOrderActions: - manage → Hauptanwendung - display → Nur Anzeige - create → Schnellerfassung - approve → Genehmigungsapp - kpi → Dashboard2. Tile-Typen richtig waehlen
| Szenario | Tile-Typ |
|---|---|
| App ohne Live-Daten | Static |
| Einzelne Kennzahl mit Trend | Dynamic |
| News-Feed | News |
| Komplexe Visualisierung | Custom (UI5) |
3. Performance beachten
- KPI-Abfragen unter 200ms halten
- Aggregationen auf DB-Ebene durchfuehren
- Caching fuer aufwaendige Berechnungen
4. Konsistente Farbgebung
| NumberState | Bedeutung | Farbe |
|---|---|---|
| Good | Positiv | Gruen |
| Neutral | Normal | Grau |
| Critical | Achtung | Rot |
| Error | Fehler | Rot (dunkel) |
Haeufige Fehler
| Problem | Ursache | Loesung |
|---|---|---|
| Tile leer | Service nicht erreichbar | Service Binding aktivieren |
| ”No data” | Falsches Entity Set | Entity Set im Target Mapping pruefen |
| Kein Refresh | Intervall = 0 | Refresh-Intervall setzen |
| Tile nicht sichtbar | Keine Berechtigung | Business Catalog zuweisen |
| Falsche Kennzahl | Property-Mapping falsch | Feldnamen in Konfiguration pruefen |
Verwandte Themen
- OData Services - Service Binding und OData-Grundlagen
- IAM Business Catalogs - Berechtigungsverwaltung fuer Tiles
- SAP Fiori Elements - UI-Generierung mit Annotations
- Fiori Overview Page (OVP) - Karten-basierte Dashboards
Zusammenfassung
Fiori Launchpad Tiles bieten verschiedene Moeglichkeiten zur App-Navigation:
| Aspekt | Static Tile | Dynamic Tile |
|---|---|---|
| Live-Daten | Nein | Ja |
| OData-Service | Nicht noetig | Erforderlich |
| Komplexitaet | Gering | Mittel |
| Use Case | Einfache Navigation | KPIs, Kennzahlen |
Kern-Implementierung:
- CDS View oder Custom Entity fuer KPI-Daten
- Service Definition und Service Binding (OData V4)
- Target Mapping im Launchpad Content Manager
- IAM Business Catalog fuer Berechtigungen
Mit Dynamic Tiles zeigst du relevante Kennzahlen direkt auf dem Launchpad und ermoeglichst Nutzern einen schnellen Ueberblick ueber wichtige Geschaeftsdaten.