[[{“value”:”
Introduction:
In SAP RAP, there are scenarios where an action needs to process multiple selected records at once rather than handling each record individually. A common example is a travel application where each Travel ID contains a Total Price, and the user selects multiple Travel IDs from the UI.
Instead of displaying a separate message for every selected Travel ID, we can calculate the combined total price of all selected records and display it as a single success message.
Travel ID Total Price
| 1 | 1,000 |
| 2 | 2,000 |
| 3 | 1,500 |
The application should calculate:
Grand Total = 1,000 + 2,000 + 1,500 = 4,500
Solution Overview:
To achieve this in RAP, the action is processed using a change set, allowing multiple selected instances to be handled together. The implementation reads the Total Price values for all selected Travel IDs, uses the ABAP REDUCE expression to calculate the grand total, and finally returns one consolidated success message to the user.
This approach is useful when implementing mass actions, multi-selection processing, aggregations, validations, or consolidated messages in SAP RAP applications.
Root Entity:
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘root entity for travel’
@Metadata.ignorePropagatedAnnotations: false
define root view entity ZRE_TRAV
as select from /dmo/travel
{
key travel_id as TravelId,
booking_fee as BookingFee,
total_price as TotalPrice,
currency_code as CurrencyCode,
description as Description,
status as Status,
lastchangedat
}
Projection View:
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘projection view for travel data’
@Metadata.ignorePropagatedAnnotations: false
define root view entity ZPJ_TRAV as projection on ZRE_TRAV
{
@UI.facet: [{ type: #IDENTIFICATION_REFERENCE }]
@UI.lineItem: [{ position: 10, type: #FOR_ACTION, dataAction: ‘UpdateStatus’, label: ‘Status’ }]
@UI.identification: [{ position: 10 }]
key TravelId,
@UI.lineItem: [{ position: 10, type: #FOR_ACTION, dataAction: ‘copyJrn’, label: ‘CopyTravel’ }]
@ui.identification: [{ position: 20 }]
BookingFee,
@UI.lineItem: [{ position: 10, type: #FOR_ACTION, dataAction: ‘TotalPrice’, label: ‘totalprice’, invocationGrouping: #CHANGE_SET }]
@ui.identification: [{ position: 30 }]
TotalPrice,
@UI.lineItem: [{ position: 10, type: #FOR_ACTION, dataAction: ‘Total’, label: ‘total’ }]
@ui.identification: [{ position: 40 }]
CurrencyCode,
@ui.lineItem: [{ position: 50 }]
@ui.identification: [{ position: 50 }]
Description,
@ui.lineItem: [{ position: 60 }]
@ui.identification: [{ position: 60 }]
@ui.selectionField: [{ position: 60 }]
@Consumption.valueHelpDefinition: [{
entity: { name: ‘ZRE_TRAV’, element: ‘Status’ },
useForValidation: true
}]
Status
}
Custom Action:
@ui.lineItem: [{ position: 10, type: #FOR_ACTION, dataAction: ‘TotalPrice’, label: ‘totalprice’, invocationGrouping: #CHANGE_SET }]
line item type should be for action displays a button on the UI to trigger the RAP action TotalPrice.
invocationgrouping:changeset ensures the action is executed as part of the same transactional change set.
Why Use CHANGESET Instead of EACH Row?
The CHANGESET processing mode is appropriate here because the action can be triggered for multiple selected records as part of the same logical operation. With CHANGESET, the implementation processes the complete set of selected instances together, allowing the application to handle the operation consistently at the change-set level. In contrast, EACHROW processes each selected record individually, which would be more appropriate when every record needs to be handled independently.
Using CHANGESET is particularly useful in this scenario because the requirement is to generate a single consolidated response for the selected records rather than execute the same message-handling logic separately for every individual record.
Behavior Definition:
managed implementation in class zbp_re_trav unique;
strict ( 2 );
define behavior for ZRE_TRAV alias re_trav
persistent table /dmo/travel
lock master
authorization master ( instance )
etag master <field_name>
{
create ( authorization : global );
update;
delete;
action (features : instance) UpdateStatus
parameter zstr_trav_status
result [1] $self;
action TotalPrice result [1] $self;
factory action copyTrn[1];
mapping for /dmo/travel{
TravelId = travel_id;
BookingFee = booking_fee;
TotalPrice = total_price;
CurrencyCode = currency_code;
Description = description;
Status = status;
}
}
Implementation:
method totalprice.
READ ENTITIES OF zre_trav IN LOCAL MODE
ENTITY re_trav
FIELDS ( TotalPrice )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_all_records).
” Calculate total
DATA(lv_grand_total) = REDUCE decfloat34(
INIT sum = 0
FOR record IN lt_all_records
NEXT sum = sum + record-TotalPrice ).
” Create message
DATA(lv_message) = |Grand Total: { lv_grand_total }|.
DATA(lo_message) = new_message(
id = ‘ZCL_MSG’
number = ‘000’
severity = if_abap_behv_message=>severity-success
v1 = lv_message
).
“Add single message
reported-re_trav = VALUE #( ( %tky = keys[ 1 ]-%tky %msg = lo_message ) ).
endmethod.
Why Does REDUCE Produce Only One Message Entry?
The REDUCE expression iterates over all selected records and accumulates their information into a single result. Although the expression processes multiple records, the accumulator represents one message structure rather than creating a new message entry for every iteration. Therefore, regardless of how many records are selected, the final result contains exactly one message entry containing the accumulated information.
This makes REDUCE useful when the requirement is to combine the results of multiple selected records into one consolidated message instead of returning separate messages for each record.
Preview:
Conclusion:
Using a RAP action with a changeset enables processing multiple selected Travel IDs in a single request. By reading all selected records, summing their TotalPrice values, and returning a single success message, users can instantly view the aggregated journey cost without navigating through individual records. This approach improves usability, reduces round trips, and demonstrates how RAP actions can efficiently handle multi-selection business scenarios while providing meaningful feedback to the user.
“}]]
Read More Technology Blog Posts by Members articles
#abap