The ABAP RESTful Application Programming Model (RAP) provides a powerful way to build modern SAP Fiori applications using behavior definitions, CDS views, and OData services.
One common requirement in business applications is allowing users to execute actions on one or multiple records while providing additional input through a dialog popup. In many scenarios, this input should be selected from a predefined list of values rather than entered manually.
A typical example is updating the category of one or more products. Users should be able to trigger an action, choose a valid category from a value help dialog, and apply the selected category to all chosen records.
This blog demonstrates how to implement an RAP Action Parameter with Value Help using a CDS Abstract Entity, CDS Value Help View, and Behavior Action. The result is a Fiori Elements application where users can execute an action and select values through standard SAP F4 help.
Actions in RAP allow developers to execute custom business logic that goes beyond standard Create, Update, and Delete operations.
An action can:
When an action requires user input, RAP automatically generates a dialog popup using an Abstract Entity.
This makes actions ideal for scenarios such as:
Consider a product management application.
Business users maintain products and their categories.
Examples:
Product ID Product Name Category
| P1001 | Laptop | ELEC |
| P1002 | Office Chair | FURN |
| P1003 | T-Shirt | CLTH |
A user selects multiple products and wants to update their category simultaneously.
Instead of editing each product individually:
All selected products are updated automatically.
If the category field is entered manually:
Example:
ELEC ✔ Valid
FURN ✔ Valid
ABCD ✖ Invalid
XYZ1 ✖ InvalidWithout a value help mechanism, users can easily enter incorrect data.
To solve this problem, we implement:
The action parameter field is linked to the value help CDS entity using:
@Consumption.valueHelpDefinitionThis automatically generates:
Create a database table to store available product categories.
@EndUserText.label : 'Product Category Table'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zprod_category {
key client : abap.clnt not null;
key category_id : abap.char(4) not null;
category_name : abap.char(40);
}This table acts as the master source for the value help.
Create a product table containing:
@EndUserText.label : 'Product Table'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #ALLOWED
define table zproduct_s {
key client : abap.clnt not null;
key product_id : abap.char(10) not null;
product_name : abap.char(40);
category : abap.char(4);
created_by : abp_creation_user;
created_at : abp_creation_tstmpl;
last_changed_by : abp_locinst_lastchange_user;
last_changed_at : abp_locinst_lastchange_tstmpl;
local_last_changed_at : abp_locinst_lastchange_tstmpl;
}This table stores the transactional product data.
Create a CDS View Entity that exposes category information.
@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Category Value Help'
@Metadata.ignorePropagatedAnnotations: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
define view entity ZI_CategoryVH
as select from zprod_category
{
key category_id as CategoryId,
category_name as CategoryName
}Explanation:
Create the RAP Root Interface View.
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Product Interface View'
@Metadata.ignorePropagatedAnnotations: true
define root view entity ZI_PRODUCT_S as select from zproduct_s
{
key product_id as ProductId,
product_name as ProductName,
category as Category,
@Semantics.user.createdBy: true
created_by as CreatedBy,
@Semantics.systemDateTime.createdAt: true
created_at as CreatedAt,
@Semantics.user.lastChangedBy: true
last_changed_by as LastChangedBy,
@Semantics.systemDateTime.lastChangedAt: true
last_changed_at as LastChangedAt,
@Semantics.systemDateTime.localInstanceLastChangedAt: true
local_last_changed_at as LocalLastChangedAt
}This view represents the Product business object.
Create the Projection View exposed to Fiori.
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Product Projection View'
@Metadata.ignorePropagatedAnnotations: true
@Metadata.allowExtensions: true
define root view entity ZC_PRODUCT
provider contract transactional_query
as projection on ZI_PRODUCT_S
{
key ProductId,
ProductName,
@Consumption.valueHelpDefinition: [{
entity: {
name: 'ZI_CATEGORYVH',
element: 'CategoryId'
}
}]
Category,
CreatedBy,
CreatedAt,
LastChangedBy,
LastChangedAt,
LocalLastChangedAt
}This enables F4 Help on the Category field.
The action dialog parameters are defined using a CDS Abstract Entity.
@EndUserText.label: 'Parameter for Set Category Action'
define abstract entity ZA_SETCATEGORY_PARAM
{
@EndUserText.label: 'New Category'
@Consumption.valueHelpDefinition: [{
entity : {
name : 'ZI_CATEGORYVH',
element : 'CategoryId'
},
useForValidation: true
}]
NewCategory : abap.char(4);
}Explanation:
Important:
useForValidation: trueprevents invalid values from being entered.
Define the RAP Action.
managed implementation in class zbp_i_product_s unique;
strict ( 2 );
define behavior for ZI_PRODUCT_S alias Product
persistent table zproduct_s
lock master
authorization master ( instance )
etag master LastChangedAt
{
create;
update;
delete;
field ( readonly ) ProductId, CreatedBy, CreatedAt,
LastChangedBy, LastChangedAt,
LocalLastChangedAt;
field ( mandatory ) ProductName;
action setCategory parameter ZA_SETCATEGORY_PARAM
result [1] $self;
mapping for zproduct_s corresponding
{
ProductId = product_id;
ProductName = product_name;
Category = category;
CreatedBy = created_by;
CreatedAt = created_at;
LastChangedBy = last_changed_by;
LastChangedAt = last_changed_at;
LocalLastChangedAt = local_last_changed_at;
}
}
In the behavior implementation class:
METHOD setcategory.The implementation:
The selected category is obtained from:
keys[ ... ]-%param-NewCategoryCLASS lhc_Product DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS get_instance_authorizations FOR INSTANCE AUTHORIZATION
IMPORTING keys REQUEST requested_authorizations FOR Product RESULT result.
METHODS setCategory FOR MODIFY
IMPORTING keys FOR ACTION Product~setCategory RESULT result.
ENDCLASS.
CLASS lhc_Product IMPLEMENTATION.
METHOD get_instance_authorizations.
ENDMETHOD.
METHOD setCategory.
" Read current product records
READ ENTITIES OF zi_product_s IN LOCAL MODE
ENTITY Product
FIELDS ( ProductId Category )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_products).
" Update category field for each selected product
MODIFY ENTITIES OF zi_product_s IN LOCAL MODE
ENTITY Product
UPDATE FIELDS ( Category )
WITH VALUE #(
FOR ls_prod IN lt_products
(
%tky = ls_prod-%tky
Category = keys[ KEY entity
%key = ls_prod-%key
]-%param-NewCategory
)
)
REPORTED DATA(lt_reported).
" Return updated records as action result
READ ENTITIES OF zi_product_s IN LOCAL MODE
ENTITY Product
ALL FIELDS
WITH CORRESPONDING #( keys )
RESULT DATA(lt_result).
result = VALUE #(
FOR ls_res IN lt_result
( %tky = ls_res-%tky
%param = ls_res )
).
ENDMETHOD.
ENDCLASS.Expose the action:
projection;
strict ( 2 );
define behavior for ZC_PRODUCT //alias <alias_name>
{
use create;
use update;
use delete;
use action setCategory;
}
Add UI annotations.
@Metadata.layer: #CORE
annotate entity ZC_PRODUCT with
{
@ui.facet: [
{
id: 'ProductInfo',
type: #IDENTIFICATION_REFERENCE,
label: 'Product Information',
position: 10
}
]
@ui.lineItem: [
{ position: 10, label: 'Product ID' },
{ type: #FOR_ACTION, dataAction: 'setCategory',
label: 'Set Category', position: 40 }
]
@ui.identification: [{ position: 10 }]
@ui.selectionField: [{ position: 10 }]
ProductId;
@ui.lineItem: [{ position: 20, label: 'Product Name' }]
@ui.identification: [{ position: 20 }]
ProductName;
@ui.lineItem: [{ position: 30, label: 'Category' }]
@ui.identification: [{ position: 30 }]
Category;
}Expose both entities.
@EndUserText.label: 'Product Service'
define service ZSD_PRODUCT {
expose ZC_PRODUCT as Product;
expose ZI_CategoryVH as CategoryVH;
}Important:
Many developers forget to expose the value help entity.
Without exposing:
ZI_CATEGORY_VHthe F4 dialog will not display any data.
Create:
OData V4 - UIservice binding.
Activate and Publish the service.
Once the application is launched, users can:
☑ P1001 Laptop
☑ P1002 Office Chair[ Set Category ]Set Category
New Category [ ] 🔍ELEC Electronics
FURN Furniture
CLTH Clothing
FOOD Food & BeveragesExample:
ELECOKSelected records are updated automatically.
P1001 Laptop ELEC
P1002 Office Chair ELECSuccess message:
Category updated successfullyIn this blog, we explored how to implement RAP Action Parameters with Value Help using a CDS Abstract Entity.
We discussed a real-world business scenario where users need to update product categories for multiple records while ensuring only valid values can be selected.
By combining a CDS Value Help View, Abstract Entity, RAP Action, and Fiori Elements annotations, we were able to create a user-friendly action dialog with built-in F4 help and validation.
This approach provides a reusable pattern for implementing parameterized actions in RAP and can easily be extended for approval processes, status updates, assignment actions, and many other business scenarios while maintaining a clean and scalable design.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
| User | Count |
|---|---|
| 90 | |
| 45 | |
| 21 | |
| 20 | |
| 15 | |
| 12 | |
| 10 | |
| 10 | |
| 10 | |
| 9 |