Value Helps (Wertehilfen) sind ein zentrales Element jeder Fiori-Anwendung. Sie ermöglichen Benutzern die komfortable Auswahl von Werten aus vordefinierten Listen. In RAP werden Value Helps deklarativ über CDS-Annotations definiert – ohne eine einzige Zeile UI-Code.
Grundkonzept der Value Helps
Value Helps in RAP basieren auf der @Consumption.valueHelpDefinition Annotation. Diese verknüpft ein Feld mit einer CDS-Entity, die als Werteliste dient.
Einfache Value Help
Das minimale Setup besteht aus der Annotation auf dem Zielfeld:
define view entity ZC_SalesOrder as projection on ZI_SalesOrder{ @Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_Customer', element: 'CustomerId' } }] key SalesOrderId, CustomerId, CustomerName, OrderDate}Diese Konfiguration zeigt automatisch eine Wertehilfe mit allen Kunden aus ZI_Customer, wenn der Benutzer das Feld CustomerId anklickt.
Struktur der Annotation
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_ValueHelpEntity', -- Name der CDS-Entity element: 'KeyField' -- Schlüsselfeld (optional) }, qualifier: 'MyValueHelp', -- Eindeutiger Bezeichner label: 'Kundenauswahl', -- Titel des Dialogs useForValidation: true, -- Validierung aktivieren additionalBinding: [{...}], -- Zusätzliche Feldzuordnungen distinctValues: true -- Nur eindeutige Werte}]Value Help Entity Design
Die Entity, die als Value Help dient, sollte speziell dafür optimiert sein:
@EndUserText.label: 'Kunden Value Help'@ObjectModel.resultSet.sizeCategory: #XS@Search.searchable: truedefine view entity ZI_CustomerVH as select from zcustomer{ @UI.hidden: true key customer_id as CustomerId,
@Search.defaultSearchElement: true @Search.fuzzinessThreshold: 0.8 customer_name as CustomerName,
@Search.defaultSearchElement: true city as City,
country as Country,
@UI.hidden: true blocked as IsBlocked}where blocked = ''Best Practices für Value Help Entities
| Aspekt | Empfehlung |
|---|---|
| Größe | @ObjectModel.resultSet.sizeCategory: #XS für kleine Listen |
| Suche | @Search.searchable für Typeahead |
| Filter | WHERE-Klausel für ungültige Einträge |
| Felder | Nur relevante Felder exponieren |
Unterschied: Einfache vs. Komplexe Value Helps
Einfache Value Help
Zeigt nur das Schlüsselfeld und optional einen Beschreibungstext:
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_StatusVH', element: 'StatusCode' }}]Status,Die Value Help Entity:
define view entity ZI_StatusVH as select from zstatus{ key status_code as StatusCode, status_text as StatusText}Komplexe Value Help
Enthält mehrere Spalten, Filter und zusätzliche Rückgabefelder:
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_MaterialVH', element: 'MaterialNumber' }, additionalBinding: [{ element: 'MaterialDescription', localElement: 'MaterialText', usage: #RESULT }, { element: 'MaterialGroup', localElement: 'MaterialGroup', usage: #RESULT }, { element: 'BaseUnit', localElement: 'Unit', usage: #RESULT }]}]MaterialNumber,MaterialText,MaterialGroup,Unit,Value Help mit Filterbedingungen
Filter schränken die angezeigten Werte ein. Es gibt zwei Arten: statische und dynamische Filter.
Statischer Filter
Filtert die Value Help auf feste Werte:
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_ProductVH', element: 'ProductId' }, additionalBinding: [{ element: 'ProductType', localConstant: 'FINISHED', usage: #FILTER }]}]ProductId,Diese Value Help zeigt nur Produkte mit ProductType = 'FINISHED'.
Dynamischer Filter (abhängig von anderen Feldern)
Der Filter basiert auf dem Wert eines anderen Feldes:
define view entity ZC_PurchaseOrder as projection on ZI_PurchaseOrder{ key PurchaseOrderId,
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_VendorVH', element: 'VendorId' }, additionalBinding: [{ element: 'PurchasingOrg', localElement: 'PurchasingOrg', usage: #FILTER }] }] VendorId,
VendorName,
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_PurchOrgVH', element: 'PurchasingOrg' } }] PurchasingOrg}Hier werden nur Lieferanten angezeigt, die zur ausgewählten Einkaufsorganisation gehören.
Mehrere Filter kombinieren
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_PlantVH', element: 'Plant' }, additionalBinding: [{ element: 'CompanyCode', localElement: 'CompanyCode', usage: #FILTER }, { element: 'SalesOrg', localElement: 'SalesOrg', usage: #FILTER }, { element: 'IsActive', localConstant: 'X', usage: #FILTER }]}]Plant,Cascading Value Helps (Abhängige Wertehilfen)
Cascading Value Helps sind untereinander abhängig – die Auswahl in einer Value Help beeinflusst die Optionen in einer anderen.
Beispiel: Land → Region → Stadt
define view entity ZC_Address as projection on ZI_Address{ key AddressId,
-- 1. Ebene: Land @Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_CountryVH', element: 'CountryCode' }, additionalBinding: [{ element: 'CountryName', localElement: 'CountryName', usage: #RESULT }] }] CountryCode, CountryName,
-- 2. Ebene: Region (gefiltert nach Land) @Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_RegionVH', element: 'RegionCode' }, additionalBinding: [{ element: 'CountryCode', localElement: 'CountryCode', usage: #FILTER }, { element: 'RegionName', localElement: 'RegionName', usage: #RESULT }] }] RegionCode, RegionName,
-- 3. Ebene: Stadt (gefiltert nach Region) @Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_CityVH', element: 'CityCode' }, additionalBinding: [{ element: 'RegionCode', localElement: 'RegionCode', usage: #FILTER }, { element: 'CityName', localElement: 'CityName', usage: #RESULT }] }] CityCode, CityName}Value Help Entities für Cascading
-- Länderdefine view entity ZI_CountryVH as select from zcountry{ key country_code as CountryCode, country_name as CountryName}
-- Regionen (mit Fremdschlüssel auf Land)define view entity ZI_RegionVH as select from zregion{ key region_code as RegionCode, region_name as RegionName, country_code as CountryCode -- Filterkriterium}
-- Städte (mit Fremdschlüssel auf Region)define view entity ZI_CityVH as select from zcity{ key city_code as CityCode, city_name as CityName, region_code as RegionCode -- Filterkriterium}Value Help mit zusätzlichen Ausgabefeldern
Zusätzliche Ausgabefelder übertragen automatisch Werte aus der Value Help in andere Felder der Entity.
Beispiel: Materialstammdaten
define view entity ZC_SalesOrderItem as projection on ZI_SalesOrderItem{ key SalesOrderId, key ItemNumber,
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_MaterialVH', element: 'MaterialNumber' }, additionalBinding: [ -- Rückgabefelder { element: 'MaterialDescription', localElement: 'MaterialText', usage: #RESULT }, { element: 'BaseUnit', localElement: 'Unit', usage: #RESULT }, { element: 'MaterialGroup', localElement: 'MatGroup', usage: #RESULT }, { element: 'GrossWeight', localElement: 'Weight', usage: #RESULT },
-- Gleichzeitig als Filter { element: 'SalesOrg', localElement: 'SalesOrg', usage: #FILTER_AND_RESULT } ] }] MaterialNumber, MaterialText, Unit, MatGroup, Weight, SalesOrg, Quantity, NetPrice}Usage-Optionen
| Wert | Beschreibung |
|---|---|
#RESULT | Wert wird zurückgegeben |
#FILTER | Wert dient als Filter |
#FILTER_AND_RESULT | Beides kombiniert |
Praktisches Beispiel: Kunde mit Adresse
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_CustomerVH', element: 'CustomerId' }, additionalBinding: [{ element: 'CustomerName', localElement: 'CustomerName', usage: #RESULT }, { element: 'Street', localElement: 'CustomerStreet', usage: #RESULT }, { element: 'City', localElement: 'CustomerCity', usage: #RESULT }, { element: 'PostalCode', localElement: 'CustomerPostalCode', usage: #RESULT }, { element: 'Country', localElement: 'CustomerCountry', usage: #RESULT }, { element: 'PaymentTerms', localElement: 'PaymentTerms', usage: #RESULT }]}]CustomerId,CustomerName,CustomerStreet,CustomerCity,CustomerPostalCode,CustomerCountry,PaymentTerms,Mehrere Value Helps für ein Feld
Ein Feld kann mehrere alternative Value Helps haben:
@Consumption.valueHelpDefinition: [ { entity: { name: 'ZI_CustomerVH', element: 'CustomerId' }, qualifier: 'AllCustomers', label: 'Alle Kunden' }, { entity: { name: 'ZI_KeyAccountVH', element: 'CustomerId' }, qualifier: 'KeyAccounts', label: 'Key Accounts', additionalBinding: [{ element: 'IsKeyAccount', localConstant: 'X', usage: #FILTER }] }, { entity: { name: 'ZI_RecentCustomerVH', element: 'CustomerId' }, qualifier: 'RecentCustomers', label: 'Zuletzt verwendet' }]CustomerId,Der Benutzer kann zwischen den Value Helps wählen.
Validierung mit Value Helps
Die Annotation useForValidation prüft eingegebene Werte gegen die Value Help:
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_CurrencyVH', element: 'CurrencyCode' }, useForValidation: true}]Currency,Bei ungültigen Eingaben zeigt Fiori automatisch eine Fehlermeldung.
Validierung in der Behavior Definition
Zusätzlich zur UI-Validierung sollte auch Backend-seitig validiert werden:
validation validateCurrency on save { field Currency; }METHOD validateCurrency. READ ENTITIES OF zi_salesorder IN LOCAL MODE ENTITY SalesOrder FIELDS ( Currency ) WITH CORRESPONDING #( keys ) RESULT DATA(lt_orders).
SELECT currency_code FROM zcurrency INTO TABLE @DATA(lt_valid_currencies).
LOOP AT lt_orders INTO DATA(ls_order). IF NOT line_exists( lt_valid_currencies[ currency_code = ls_order-Currency ] ). APPEND VALUE #( %tky = ls_order-%tky %msg = new_message_with_text( severity = if_abap_behv_message=>severity-error text = |Währung { ls_order-Currency } ist ungültig| ) %element-Currency = if_abap_behv=>mk-on ) TO reported-salesorder.
APPEND VALUE #( %tky = ls_order-%tky ) TO failed-salesorder. ENDIF. ENDLOOP.ENDMETHOD.Collective Value Helps
Für Felder, die in mehreren Views verwendet werden, können zentrale Value Helps definiert werden:
-- Zentrale Value Help Definition@ObjectModel.usageType: { sizeCategory: #S, serviceQuality: #A, dataClass: #CUSTOMIZING}define view entity ZI_CountryCollVH as select from I_Country{ key Country as CountryCode, _Text.CountryName as CountryName}Diese kann dann in verschiedenen Views referenziert werden:
-- In View 1@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_CountryCollVH', element: 'CountryCode' }}]ShipToCountry,
-- In View 2@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_CountryCollVH', element: 'CountryCode' }}]BillToCountry,Typische Fehler und Lösungen
Fehler 1: Value Help zeigt keine Daten
Symptom: Der Value Help Dialog öffnet sich, aber ist leer.
Ursache: Die Value Help Entity hat keine Daten oder einen falschen Filter.
Lösung:
-- Prüfen mit SE16/ADTSELECT * FROM zi_customerVH.
-- Filter entfernen oder korrigierendefine view entity ZI_CustomerVH as select from zcustomer{ key customer_id as CustomerId}-- WHERE-Klausel prüfenFehler 2: Zusätzliche Felder werden nicht gefüllt
Symptom: Das Hauptfeld wird gefüllt, aber additionalBinding-Felder bleiben leer.
Ursache: Feldnamen stimmen nicht überein oder usage: #RESULT fehlt.
Lösung:
additionalBinding: [{ element: 'CustomerName', -- Muss exakt dem Feldnamen in der VH Entity entsprechen localElement: 'CustomerName', -- Muss exakt dem Feldnamen in der Projection entsprechen usage: #RESULT -- Nicht vergessen!}]Fehler 3: Cascading funktioniert nicht
Symptom: Abhängige Value Help zeigt alle Werte, nicht nur gefilterte.
Ursache: Das Filterfeld fehlt in der Value Help Entity.
Lösung:
-- Die VH Entity muss das Filterfeld enthaltendefine view entity ZI_RegionVH as select from zregion{ key region_code as RegionCode, region_name as RegionName, country_code as CountryCode -- Dieses Feld wird zum Filtern benötigt}Fehler 4: Performance-Probleme
Symptom: Value Help lädt langsam oder verursacht Timeouts.
Ursache: Große Datenmenge ohne Paginierung oder fehlende Indizes.
Lösung:
-- Größenkategorie setzen@ObjectModel.resultSet.sizeCategory: #XS -- <100 Einträge@ObjectModel.resultSet.sizeCategory: #S -- <1000 Einträge
-- Suche optimieren für Typeahead@Search.searchable: truedefine view entity ZI_LargeDataVH{ @Search.defaultSearchElement: true @Search.ranking: #HIGH key KeyField,
@Search.defaultSearchElement: true TextField}Fehler 5: Validierungsfehler bei gültigen Werten
Symptom: Die Eingabe wird als ungültig abgelehnt, obwohl sie in der Value Help existiert.
Ursache: Case-Sensitivity oder führende/nachfolgende Leerzeichen.
Lösung:
-- In der Value Help Entitydefine view entity ZI_StatusVH as select from zstatus{ key upper( status_code ) as StatusCode, -- Case-insensitive status_text as StatusText}Fehler 6: Value Help öffnet sich nicht
Symptom: Kein Value Help Icon oder Dialog.
Ursache: Die Annotation ist auf dem falschen Feld oder die Entity existiert nicht.
Lösung:
-- Annotation muss auf dem editierbaren Feld sein@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_CustomerVH', element: 'CustomerId' } -- Entity-Name prüfen}]CustomerId, -- Nicht auf berechneten oder virtuellen FeldernErweiterte Techniken
Distinct Values
Für Felder mit Duplikaten:
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_OrderStatusVH', element: 'Status' }, distinctValues: true}]Status,Text-Arrangement für Value Helps
@ObjectModel.text.element: ['StatusText']@UI.textArrangement: #TEXT_FIRST@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_StatusVH', element: 'StatusCode' }}]StatusCode,Value Help mit Assoziation
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_CustomerVH' }, association: '_Customer'}]@ObjectModel.foreignKey.association: '_Customer'CustomerId,
_CustomerZusammenfassung
| Feature | Annotation/Eigenschaft |
|---|---|
| Basis Value Help | @Consumption.valueHelpDefinition |
| Filterung | additionalBinding mit usage: #FILTER |
| Rückgabefelder | additionalBinding mit usage: #RESULT |
| Cascading | Kombination von #FILTER auf abhängigen Feldern |
| Validierung | useForValidation: true |
| Mehrere VH | Array mit verschiedenen qualifier |
| Performance | @ObjectModel.resultSet.sizeCategory |
Value Helps sind ein mächtiges Werkzeug für benutzerfreundliche Fiori-Anwendungen. Mit der richtigen Kombination aus CDS-Annotations lassen sich komplexe Szenarien wie abhängige Wertehilfen und automatische Feldübernahmen vollständig deklarativ umsetzen.
Verwandte Themen
- CDS Annotations - Alle CDS Annotationen im Überblick
- RAP Grundlagen - Grundlagen des RESTful ABAP Programming
- Search Helps - Klassische Suchhilfen in ABAP