RAP - Action (Part 2)
The second part for the actions in RAP follows, in which we want to go into further details in the use and to show special cases.
Table of contents
In the first part of this article, we mainly dealt with the integration of actions in a simple and static form. In this article we want to talk a bit about self-references and factory actions and what they are used for.
Return values
In the last article we defined two actions without return parameters, so that the caller does not receive any corresponding information when they are executed, but instead has to read the data record again to get the current data, for example. You can do this work by defining a return parameter and filling it after calling the method.
To do this, we extend the definition of the action in the behavior definition. After the keyword "result" comes the cardinality, as you know it from Core Data Services. This is followed by the return type that the method returns.
action fillEmptyStreets result [1] $self;
The $self reference refers to the entity in which the action was defined. An instance of the data type "ZBS_I_RAPPartner" is therefore returned. The implementation must now be regenerated accordingly or extended by the RESULT addition.
METHODS fillemptystreets FOR MODIFY
IMPORTING keys FOR ACTION partner~fillemptystreets RESULT result.
Without the implementation of the return value, i.e. no further change, navigation occurs when the action is executed. However, the displayed image is then also empty because no instance was returned. With the new addition, there is always navigation to the corresponding entity and the overview screen is exited.
We now add the new coding at the end of the method to fill the "result" and return the data of the entity.
READ ENTITIES OF ZBS_I_RAPPartner IN LOCAL MODE
ENTITY Partner
FIELDS ( Street )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_partner_data).
LOOP AT lt_partner_data INTO DATA(ls_partner) WHERE Street IS INITIAL.
ls_partner-Street = 'EMPTY'.
MODIFY ENTITIES OF ZBS_I_RAPPartner IN LOCAL MODE
ENTITY Partner
UPDATE FIELDS ( Street )
WITH VALUE #( ( %tky = ls_partner-%tky Street = ls_partner-Street %control-Street = if_abap_behv=>mk-on ) ).
INSERT VALUE #( %tky = ls_partner-%tky %param = ls_partner ) INTO TABLE result.
ENDLOOP.
Within the loop, we now fill the result with the key (%TKY) and the new data in the Parameter field. The data could also simply be read from the database using READ to ensure that the current data is made available. If the data is transferred correctly, you no longer jump to the detail screen.
Hint: Return values can be of the following types: structures, entities, abstract entities.
Factory Action
As the name describes, such a method generates an instance of the current entity, which can happen when copying, among other things. The definition therefore deviates somewhat. The keyword "factory" is introduced. A cardinality is given at the end, but the "result" can be omitted, since $self is always used.
factory action copyLine [1];
You can use the Quick Fix (CTRL + 1) to generate the method in the behavior implementation and only have to develop the implementation. The new coding is now a bit more extensive:
DATA:
lt_creation TYPE TABLE FOR CREATE ZBS_I_RAPPartner.
READ ENTITIES OF ZBS_I_RAPPartner IN LOCAL MODE
ENTITY Partner ALL FIELDS WITH CORRESPONDING #( keys )
RESULT DATA(lt_partner_data).
SELECT FROM zbs_dmo_partner
FIELDS MAX( partner )
INTO @DATA(ld_number).
LOOP AT lt_partner_data INTO DATA(ls_partner).
ld_number += 1.
ls_partner-PartnerNumber = ld_number.
ls_partner-PartnerName &&= | copy|.
INSERT VALUE #( %cid = keys[ sy-tabix ]-%cid ) INTO TABLE lt_creation REFERENCE INTO DATA(lr_create).
lr_create->* = CORRESPONDING #( ls_partner ).
lr_create->%control-PartnerNumber = if_abap_behv=>mk-on.
lr_create->%control-PartnerName = if_abap_behv=>mk-on.
lr_create->%control-Street = if_abap_behv=>mk-on.
lr_create->%control-City = if_abap_behv=>mk-on.
lr_create->%control-Country = if_abap_behv=>mk-on.
lr_create->%control-PaymentCurrency = if_abap_behv=>mk-on.
ENDLOOP.
MODIFY ENTITIES OF ZBS_I_RAPPartner IN LOCAL MODE
ENTITY Partner CREATE FROM lt_creation
FAILED DATA(ls_failed)
MAPPED DATA(ls_mapped)
REPORTED DATA(ls_reported).
mapped-partner = ls_mapped-partner.
In the first step, we read the marked record and create a table of data records to be created for it. First we determine the highest partner number and assign the number plus 1. Since the partner number is the key, the number must always be unique. The new data records are then transferred to the database using MODIFY. The commit must not be set within the processing and is carried out by the framework. Finally, we transfer the data from the MAPPED structure to the MAPPED parameter of the structure.
Hint: It is particularly important that the transferred CID is also returned, otherwise you will get an empty detail screen.
EML
Actions can also be triggered via EML using the MODIFY statement. Accordingly, you only have to specify the action to be triggered and the key of the data record. The RESULT is particularly important for the return, since the return is contained here.
MODIFY ENTITIES OF ZBS_I_RAPPartner
ENTITY Partner EXECUTE fillEmptyStreets
FROM VALUE #( ( PartnerNumber = '1000000007' ) )
RESULT DATA(lt_new_partner)
MAPPED DATA(ls_mapped)
FAILED DATA(ls_failed)
REPORTED DATA(ls_reported).
COMMIT ENTITIES.
In this case, the COMMIT is also important so that the action is triggered. Mapped, Failed and Reported are not strictly required, but complete the result. The result now looks like this:
Here is the full class for this example:
CLASS zcl_bs_demo_action_eml DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_bs_demo_action_eml IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
MODIFY ENTITIES OF ZBS_I_RAPPartner
ENTITY Partner EXECUTE fillEmptyStreets
FROM VALUE #( ( PartnerNumber = '1000000007' ) )
RESULT DATA(lt_new_partner)
MAPPED DATA(ls_mapped)
FAILED DATA(ls_failed)
REPORTED DATA(ls_reported).
COMMIT ENTITIES.
IF line_exists( lt_new_partner[ 1 ] ).
out->write( lt_new_partner[ 1 ]-PartnerNumber ).
out->write( lt_new_partner[ 1 ]-%param ).
ELSE.
out->write( `Not worked` ).
ENDIF.
ENDMETHOD.
ENDCLASS.
Conclusion
There are many different approaches you can take in the field of actions and depending on how an action is supposed to work, you also have to take different things into account. The return value of the action can optionally also be important, but does not always have to be filled.