Value Helps are a central element of every Fiori application. They enable users to conveniently select values from predefined lists. In RAP, Value Helps are defined declaratively via CDS annotations - without a single line of UI code.
Basic Concept of Value Helps
Value Helps in RAP are based on the @Consumption.valueHelpDefinition annotation. This links a field with a CDS entity that serves as the value list.
Simple Value Help
The minimal setup consists of the annotation on the target field:
define view entity ZC_SalesOrder as projection on ZI_SalesOrder{ @Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_Customer', element: 'CustomerId' } }] key SalesOrderId, CustomerId, CustomerName, OrderDate}This configuration automatically displays a value help with all customers from ZI_Customer when the user clicks the CustomerId field.
Structure of the Annotation
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_ValueHelpEntity', -- Name of the CDS entity element: 'KeyField' -- Key field (optional) }, qualifier: 'MyValueHelp', -- Unique identifier label: 'Customer Selection', -- Dialog title useForValidation: true, -- Enable validation additionalBinding: [{...}], -- Additional field mappings distinctValues: true -- Unique values only}]Value Help Entity Design
The entity serving as a Value Help should be specifically optimized for this purpose:
@EndUserText.label: 'Customer 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 for Value Help Entities
| Aspect | Recommendation |
|---|---|
| Size | @ObjectModel.resultSet.sizeCategory: #XS for small lists |
| Search | @Search.searchable for typeahead |
| Filter | WHERE clause for invalid entries |
| Fields | Only expose relevant fields |
Difference: Simple vs. Complex Value Helps
Simple Value Help
Shows only the key field and optionally a description text:
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_StatusVH', element: 'StatusCode' }}]Status,The Value Help Entity:
define view entity ZI_StatusVH as select from zstatus{ key status_code as StatusCode, status_text as StatusText}Complex Value Help
Contains multiple columns, filters, and additional return fields:
@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 with Filter Conditions
Filters restrict the displayed values. There are two types: static and dynamic filters.
Static Filter
Filters the Value Help to fixed values:
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_ProductVH', element: 'ProductId' }, additionalBinding: [{ element: 'ProductType', localConstant: 'FINISHED', usage: #FILTER }]}]ProductId,This Value Help shows only products with ProductType = 'FINISHED'.
Dynamic Filter (dependent on other fields)
The filter is based on the value of another field:
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}Here, only vendors belonging to the selected purchasing organization are displayed.
Combining Multiple Filters
@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 (Dependent Value Helps)
Cascading Value Helps are interdependent - the selection in one Value Help affects the options in another.
Example: Country → Region → City
define view entity ZC_Address as projection on ZI_Address{ key AddressId,
-- Level 1: Country @Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_CountryVH', element: 'CountryCode' }, additionalBinding: [{ element: 'CountryName', localElement: 'CountryName', usage: #RESULT }] }] CountryCode, CountryName,
-- Level 2: Region (filtered by country) @Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_RegionVH', element: 'RegionCode' }, additionalBinding: [{ element: 'CountryCode', localElement: 'CountryCode', usage: #FILTER }, { element: 'RegionName', localElement: 'RegionName', usage: #RESULT }] }] RegionCode, RegionName,
-- Level 3: City (filtered by 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 for Cascading
-- Countriesdefine view entity ZI_CountryVH as select from zcountry{ key country_code as CountryCode, country_name as CountryName}
-- Regions (with foreign key to country)define view entity ZI_RegionVH as select from zregion{ key region_code as RegionCode, region_name as RegionName, country_code as CountryCode -- Filter criterion}
-- Cities (with foreign key to region)define view entity ZI_CityVH as select from zcity{ key city_code as CityCode, city_name as CityName, region_code as RegionCode -- Filter criterion}Value Help with Additional Output Fields
Additional output fields automatically transfer values from the Value Help to other fields in the entity.
Example: Material Master Data
define view entity ZC_SalesOrderItem as projection on ZI_SalesOrderItem{ key SalesOrderId, key ItemNumber,
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_MaterialVH', element: 'MaterialNumber' }, additionalBinding: [ -- Return fields { element: 'MaterialDescription', localElement: 'MaterialText', usage: #RESULT }, { element: 'BaseUnit', localElement: 'Unit', usage: #RESULT }, { element: 'MaterialGroup', localElement: 'MatGroup', usage: #RESULT }, { element: 'GrossWeight', localElement: 'Weight', usage: #RESULT },
-- Also as filter { element: 'SalesOrg', localElement: 'SalesOrg', usage: #FILTER_AND_RESULT } ] }] MaterialNumber, MaterialText, Unit, MatGroup, Weight, SalesOrg, Quantity, NetPrice}Usage Options
| Value | Description |
|---|---|
#RESULT | Value is returned |
#FILTER | Value serves as filter |
#FILTER_AND_RESULT | Both combined |
Practical Example: Customer with Address
@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,Multiple Value Helps for One Field
A field can have multiple alternative Value Helps:
@Consumption.valueHelpDefinition: [ { entity: { name: 'ZI_CustomerVH', element: 'CustomerId' }, qualifier: 'AllCustomers', label: 'All Customers' }, { 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: 'Recently Used' }]CustomerId,The user can choose between the Value Helps.
Validation with Value Helps
The annotation useForValidation validates entered values against the Value Help:
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_CurrencyVH', element: 'CurrencyCode' }, useForValidation: true}]Currency,For invalid entries, Fiori automatically displays an error message.
Validation in the Behavior Definition
In addition to UI validation, backend validation should also be implemented:
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 = |Currency { ls_order-Currency } is invalid| ) %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
For fields used in multiple views, central Value Helps can be defined:
-- Central 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}This can then be referenced in different views:
-- In View 1@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_CountryCollVH', element: 'CountryCode' }}]ShipToCountry,
-- In View 2@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_CountryCollVH', element: 'CountryCode' }}]BillToCountry,Common Errors and Solutions
Error 1: Value Help Shows No Data
Symptom: The Value Help dialog opens but is empty.
Cause: The Value Help entity has no data or an incorrect filter.
Solution:
-- Check with SE16/ADTSELECT * FROM zi_customerVH.
-- Remove or correct filterdefine view entity ZI_CustomerVH as select from zcustomer{ key customer_id as CustomerId}-- Check WHERE clauseError 2: Additional Fields Are Not Filled
Symptom: The main field is filled, but additionalBinding fields remain empty.
Cause: Field names don’t match or usage: #RESULT is missing.
Solution:
additionalBinding: [{ element: 'CustomerName', -- Must exactly match field name in VH Entity localElement: 'CustomerName', -- Must exactly match field name in Projection usage: #RESULT -- Don't forget!}]Error 3: Cascading Doesn’t Work
Symptom: Dependent Value Help shows all values, not just filtered ones.
Cause: The filter field is missing in the Value Help entity.
Solution:
-- The VH Entity must contain the filter fielddefine view entity ZI_RegionVH as select from zregion{ key region_code as RegionCode, region_name as RegionName, country_code as CountryCode -- This field is needed for filtering}Error 4: Performance Problems
Symptom: Value Help loads slowly or causes timeouts.
Cause: Large data volume without pagination or missing indexes.
Solution:
-- Set size category@ObjectModel.resultSet.sizeCategory: #XS -- <100 entries@ObjectModel.resultSet.sizeCategory: #S -- <1000 entries
-- Optimize search for typeahead@Search.searchable: truedefine view entity ZI_LargeDataVH{ @Search.defaultSearchElement: true @Search.ranking: #HIGH key KeyField,
@Search.defaultSearchElement: true TextField}Error 5: Validation Errors for Valid Values
Symptom: Input is rejected as invalid even though it exists in the Value Help.
Cause: Case sensitivity or leading/trailing whitespace.
Solution:
-- In the Value Help Entitydefine view entity ZI_StatusVH as select from zstatus{ key upper( status_code ) as StatusCode, -- Case-insensitive status_text as StatusText}Error 6: Value Help Doesn’t Open
Symptom: No Value Help icon or dialog.
Cause: The annotation is on the wrong field or the entity doesn’t exist.
Solution:
-- Annotation must be on the editable field@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_CustomerVH', element: 'CustomerId' } -- Check entity name}]CustomerId, -- Not on calculated or virtual fieldsAdvanced Techniques
Distinct Values
For fields with duplicates:
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_OrderStatusVH', element: 'Status' }, distinctValues: true}]Status,Text Arrangement for Value Helps
@ObjectModel.text.element: ['StatusText']@UI.textArrangement: #TEXT_FIRST@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_StatusVH', element: 'StatusCode' }}]StatusCode,Value Help with Association
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_CustomerVH' }, association: '_Customer'}]@ObjectModel.foreignKey.association: '_Customer'CustomerId,
_CustomerSummary
| Feature | Annotation/Property |
|---|---|
| Basic Value Help | @Consumption.valueHelpDefinition |
| Filtering | additionalBinding with usage: #FILTER |
| Return fields | additionalBinding with usage: #RESULT |
| Cascading | Combination of #FILTER on dependent fields |
| Validation | useForValidation: true |
| Multiple VH | Array with different qualifier |
| Performance | @ObjectModel.resultSet.sizeCategory |
Value Helps are a powerful tool for user-friendly Fiori applications. With the right combination of CDS annotations, complex scenarios like dependent value helps and automatic field transfers can be implemented entirely declaratively.
Related Topics
- CDS Annotations - All CDS annotations overview
- RAP Basics - RESTful ABAP Programming fundamentals
- Search Helps - Classic search helps in ABAP