Los Value Helps (ayudas de valores) son un elemento central de cualquier aplicación Fiori. Permiten a los usuarios seleccionar cómodamente valores de listas predefinidas. En RAP los Value Helps se definen declarativamente mediante anotaciones CDS, sin escribir una sola línea de código UI.
Concepto Básico de Value Helps
Los Value Helps en RAP se basan en la anotación @Consumption.valueHelpDefinition. Esta vincula un campo con una entidad CDS que sirve como lista de valores.
Value Help Simple
La configuración mínima consiste en la anotación en el campo objetivo:
define view entity ZC_SalesOrder as projection on ZI_SalesOrder{ @Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_Customer', element: 'CustomerId' } }] key SalesOrderId, CustomerId, CustomerName, OrderDate}Esta configuración muestra automáticamente una ayuda de valores con todos los clientes de ZI_Customer cuando el usuario hace clic en el campo CustomerId.
Estructura de la Anotación
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_ValueHelpEntity', -- Nombre de la entidad CDS element: 'KeyField' -- Campo clave (opcional) }, qualifier: 'MyValueHelp', -- Identificador único label: 'Selección de Cliente', -- Título del diálogo useForValidation: true, -- Activar validación additionalBinding: [{...}], -- Asignaciones de campos adicionales distinctValues: true -- Solo valores únicos}]Diseño de Entidad Value Help
La entidad que sirve como Value Help debe estar optimizada específicamente para este propósito:
@EndUserText.label: 'Value Help de Clientes'@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 = ''Mejores Prácticas para Entidades Value Help
| Aspecto | Recomendación |
|---|---|
| Tamaño | @ObjectModel.resultSet.sizeCategory: #XS para listas pequeñas |
| Búsqueda | @Search.searchable para Typeahead |
| Filtro | Cláusula WHERE para entradas inválidas |
| Campos | Exponer solo campos relevantes |
Diferencia: Value Helps Simples vs. Complejos
Value Help Simple
Muestra solo el campo clave y opcionalmente un texto descriptivo:
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_StatusVH', element: 'StatusCode' }}]Status,La entidad Value Help:
define view entity ZI_StatusVH as select from zstatus{ key status_code as StatusCode, status_text as StatusText}Value Help Complejo
Contiene múltiples columnas, filtros y campos de retorno adicionales:
@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 con Condiciones de Filtro
Los filtros restringen los valores mostrados. Hay dos tipos: filtros estáticos y dinámicos.
Filtro Estático
Filtra el Value Help a valores fijos:
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_ProductVH', element: 'ProductId' }, additionalBinding: [{ element: 'ProductType', localConstant: 'FINISHED', usage: #FILTER }]}]ProductId,Este Value Help muestra solo productos con ProductType = 'FINISHED'.
Filtro Dinámico (dependiente de otros campos)
El filtro se basa en el valor de otro campo:
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}Aquí solo se muestran los proveedores que pertenecen a la organización de compras seleccionada.
Combinar Múltiples Filtros
@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 (Ayudas de Valores Dependientes)
Los Cascading Value Helps son dependientes entre sí: la selección en un Value Help influye en las opciones de otro.
Ejemplo: País -> Región -> Ciudad
define view entity ZC_Address as projection on ZI_Address{ key AddressId,
-- 1er Nivel: País @Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_CountryVH', element: 'CountryCode' }, additionalBinding: [{ element: 'CountryName', localElement: 'CountryName', usage: #RESULT }] }] CountryCode, CountryName,
-- 2do Nivel: Región (filtrada por País) @Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_RegionVH', element: 'RegionCode' }, additionalBinding: [{ element: 'CountryCode', localElement: 'CountryCode', usage: #FILTER }, { element: 'RegionName', localElement: 'RegionName', usage: #RESULT }] }] RegionCode, RegionName,
-- 3er Nivel: Ciudad (filtrada por Región) @Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_CityVH', element: 'CityCode' }, additionalBinding: [{ element: 'RegionCode', localElement: 'RegionCode', usage: #FILTER }, { element: 'CityName', localElement: 'CityName', usage: #RESULT }] }] CityCode, CityName}Entidades Value Help para Cascading
-- Paísesdefine view entity ZI_CountryVH as select from zcountry{ key country_code as CountryCode, country_name as CountryName}
-- Regiones (con clave foránea a País)define view entity ZI_RegionVH as select from zregion{ key region_code as RegionCode, region_name as RegionName, country_code as CountryCode -- Criterio de filtro}
-- Ciudades (con clave foránea a Región)define view entity ZI_CityVH as select from zcity{ key city_code as CityCode, city_name as CityName, region_code as RegionCode -- Criterio de filtro}Value Help con Campos de Salida Adicionales
Los campos de salida adicionales transfieren automáticamente valores del Value Help a otros campos de la entidad.
Ejemplo: Datos Maestros de Material
define view entity ZC_SalesOrderItem as projection on ZI_SalesOrderItem{ key SalesOrderId, key ItemNumber,
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_MaterialVH', element: 'MaterialNumber' }, additionalBinding: [ -- Campos de retorno { element: 'MaterialDescription', localElement: 'MaterialText', usage: #RESULT }, { element: 'BaseUnit', localElement: 'Unit', usage: #RESULT }, { element: 'MaterialGroup', localElement: 'MatGroup', usage: #RESULT }, { element: 'GrossWeight', localElement: 'Weight', usage: #RESULT },
-- Simultáneamente como filtro { element: 'SalesOrg', localElement: 'SalesOrg', usage: #FILTER_AND_RESULT } ] }] MaterialNumber, MaterialText, Unit, MatGroup, Weight, SalesOrg, Quantity, NetPrice}Opciones de Usage
| Valor | Descripción |
|---|---|
#RESULT | El valor se devuelve |
#FILTER | El valor sirve como filtro |
#FILTER_AND_RESULT | Ambos combinados |
Ejemplo Práctico: Cliente con Dirección
@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,Múltiples Value Helps para un Campo
Un campo puede tener múltiples Value Helps alternativos:
@Consumption.valueHelpDefinition: [ { entity: { name: 'ZI_CustomerVH', element: 'CustomerId' }, qualifier: 'AllCustomers', label: 'Todos los Clientes' }, { 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: 'Usados Recientemente' }]CustomerId,El usuario puede elegir entre los Value Helps.
Validación con Value Helps
La anotación useForValidation verifica los valores ingresados contra el Value Help:
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_CurrencyVH', element: 'CurrencyCode' }, useForValidation: true}]Currency,Para entradas inválidas, Fiori muestra automáticamente un mensaje de error.
Validación en la Behavior Definition
Además de la validación UI, también debe validarse en el backend:
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 = |Moneda { ls_order-Currency } es inválida| ) %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
Para campos que se usan en múltiples views, se pueden definir Value Helps centrales:
-- Definición central de Value Help@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}Esta puede referenciarse en diferentes views:
-- En View 1@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_CountryCollVH', element: 'CountryCode' }}]ShipToCountry,
-- En View 2@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_CountryCollVH', element: 'CountryCode' }}]BillToCountry,Errores Típicos y Soluciones
Error 1: Value Help no Muestra Datos
Síntoma: El diálogo del Value Help se abre, pero está vacío.
Causa: La entidad Value Help no tiene datos o tiene un filtro incorrecto.
Solución:
-- Verificar con SE16/ADTSELECT * FROM zi_customerVH.
-- Eliminar o corregir filtrodefine view entity ZI_CustomerVH as select from zcustomer{ key customer_id as CustomerId}-- Verificar cláusula WHEREError 2: Campos Adicionales no se Llenan
Síntoma: El campo principal se llena, pero los campos de additionalBinding quedan vacíos.
Causa: Los nombres de campo no coinciden o falta usage: #RESULT.
Solución:
additionalBinding: [{ element: 'CustomerName', -- Debe coincidir exactamente con el nombre en la Entidad VH localElement: 'CustomerName', -- Debe coincidir exactamente con el nombre en la Projection usage: #RESULT -- ¡No olvidar!}]Error 3: Cascading no Funciona
Síntoma: El Value Help dependiente muestra todos los valores, no solo los filtrados.
Causa: El campo de filtro falta en la entidad Value Help.
Solución:
-- La entidad VH debe contener el campo de filtrodefine view entity ZI_RegionVH as select from zregion{ key region_code as RegionCode, region_name as RegionName, country_code as CountryCode -- Este campo se necesita para filtrar}Error 4: Problemas de Performance
Síntoma: Value Help carga lento o causa timeouts.
Causa: Gran cantidad de datos sin paginación o índices faltantes.
Solución:
-- Establecer categoría de tamaño@ObjectModel.resultSet.sizeCategory: #XS -- <100 entradas@ObjectModel.resultSet.sizeCategory: #S -- <1000 entradas
-- Optimizar búsqueda para Typeahead@Search.searchable: truedefine view entity ZI_LargeDataVH{ @Search.defaultSearchElement: true @Search.ranking: #HIGH key KeyField,
@Search.defaultSearchElement: true TextField}Error 5: Errores de Validación en Valores Válidos
Síntoma: La entrada se rechaza como inválida, aunque existe en el Value Help.
Causa: Sensibilidad a mayúsculas/minúsculas o espacios al inicio/final.
Solución:
-- En la entidad Value Helpdefine view entity ZI_StatusVH as select from zstatus{ key upper( status_code ) as StatusCode, -- Case-insensitive status_text as StatusText}Error 6: Value Help no se Abre
Síntoma: No hay icono de Value Help ni diálogo.
Causa: La anotación está en el campo incorrecto o la entidad no existe.
Solución:
-- La anotación debe estar en el campo editable@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_CustomerVH', element: 'CustomerId' } -- Verificar nombre de entidad}]CustomerId, -- No en campos calculados o virtualesTécnicas Avanzadas
Distinct Values
Para campos con duplicados:
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_OrderStatusVH', element: 'Status' }, distinctValues: true}]Status,Text-Arrangement para Value Helps
@ObjectModel.text.element: ['StatusText']@UI.textArrangement: #TEXT_FIRST@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_StatusVH', element: 'StatusCode' }}]StatusCode,Value Help con Asociación
@Consumption.valueHelpDefinition: [{ entity: { name: 'ZI_CustomerVH' }, association: '_Customer'}]@ObjectModel.foreignKey.association: '_Customer'CustomerId,
_CustomerResumen
| Característica | Anotación/Propiedad |
|---|---|
| Value Help Básico | @Consumption.valueHelpDefinition |
| Filtrado | additionalBinding con usage: #FILTER |
| Campos de Retorno | additionalBinding con usage: #RESULT |
| Cascading | Combinación de #FILTER en campos dependientes |
| Validación | useForValidation: true |
| Múltiples VH | Array con diferentes qualifier |
| Performance | @ObjectModel.resultSet.sizeCategory |
Los Value Helps son una herramienta poderosa para aplicaciones Fiori amigables. Con la combinación correcta de anotaciones CDS se pueden implementar escenarios complejos como ayudas de valores dependientes y transferencia automática de campos de forma completamente declarativa.
Temas Relacionados
- CDS Annotations - Todas las Anotaciones CDS en Resumen
- Fundamentos RAP - Fundamentos de RESTful ABAP Programming
- Search Helps - Ayudas de Búsqueda Clásicas en ABAP