Skip to Content
Technical Articles
Author's profile photo ramjee korada

ABAP RAP : Enabling custom actions with a dialog for additional input fields

Prerequisites:

  • Knowledge on ABAP Restful Application Programming
  • Knowledge on Entity Manipulation Language (EML)
  • [Optional] Hands on exercises in OpenSAP course https://open.sap.com/courses/cp13.

This blog gives you an idea to develop a custom action with a dialog for additional input fields that are needed based on scenario.

  • Use case:
    • There is a purchase contract that needs to be extended to next year by buyer.
  • Business logic:
    • Only extend those validities which are running on existing valid to
      • [i.e. continue business with same supplier].
    • Don’t touch items which are older than existing valid to.
      • [i.e. no need to continue business with this supplier]

In my example: 

Old valid to: Jun 30, 2021

New valid to: Dec 31, 2021

Item #10 runs on Jun 30,2021 hence it is expected to extend till Dec 31, 2021

Item #20 ends on Mar 31, 2021 hence it is not expected to touch.

Click the button Extend and to see results on Object page and item page

 

Implementation steps:

  1. Create a data model with Header (Parent), Item (Child), Conditions (Grand Child) having fields “Valid from”, “Valid to “.
  2. Create an abstract CDS entity with required input fields.
@EndUserText.label: 'Abstract entity to extend the validity'
@Metadata.allowExtensions: true
define abstract entity ZRK_A_Doc_Extend 
 // with parameters parameter_name : parameter_type 
  {
    extend_till : /dmo/end_date;
    comments : abap.string( 300 );
    
}

3.Enrich the entity with UI annotations such as labels.

@Metadata.layer: #CORE
annotate entity ZRK_A_Doc_Extend
    with 
{
   @EndUserText.label: 'New validity to:'
   extend_till; 
   @EndUserText.label: 'Enter your comments:'
   comments;
    
}

4. In Behavior Definition, define action “extendDoc” with parameter using the abstract entity                created in step#2.

  action extendDoc parameter ZRK_A_Doc_Extend result [1] $self;

       5. Implement the core ABAP logic for extend in Behavior Pool Class

METHOD extendDoc.

    DATA : lt_update_doc  TYPE TABLE FOR UPDATE zrk_i_doc_head.
    DATA(lt_keys) = keys.
    DATA(lv_today) = cl_abap_context_info=>get_system_date( ).

    LOOP AT lt_keys ASSIGNING FIELD-SYMBOL(<fs_key>).

      IF <fs_key>-%param-extend_till < lv_today.

        APPEND VALUE #( %tky                = <fs_key>-%tky ) TO failed-head.

        APPEND VALUE #( %tky                = <fs_key>-%tky
                        %msg                = new_message(  id       = 'ZRK_CM_DOC'
                                                            number   = '001' " Document cannot be extended into the past
                                                            severity = if_abap_behv_message=>severity-error )
                        %element-ValidTo = if_abap_behv=>mk-on ) TO reported-head.

        DELETE lt_keys.


      ELSE.
        DATA(lv_new_valid_to) = <fs_key>-%param-extend_till.
      ENDIF.

    ENDLOOP.

    " Once the validations are passed, proceed with extending document.
    CHECK lt_keys IS NOT INITIAL.

    READ ENTITIES OF zrk_i_doc_head IN LOCAL MODE
        ENTITY Head
        FIELDS ( ValidFrom ValidTo )
        WITH CORRESPONDING #( keys )
        RESULT DATA(lt_doc_head).


    CHECK lt_doc_head IS NOT INITIAL.

    LOOP AT lt_doc_head ASSIGNING FIELD-SYMBOL(<fs_head>).

      " Capture old valid to
      DATA(lv_old_valid_to) = <fs_head>-ValidTo.

      " Read items from entity
      READ ENTITIES OF zrk_i_doc_head IN LOCAL MODE
          ENTITY Head BY \_Items
          FIELDS ( ValidFrom ValidTo )
          WITH VALUE #( ( %tky = <fs_head>-%tky ) )
          RESULT DATA(lt_items).

      " Loop through items that are running on old valid to
      LOOP AT lt_items ASSIGNING FIELD-SYMBOL(<fs_item>)
                            WHERE ValidFrom LE lv_old_valid_to
                               AND ValidTo GE lv_old_valid_to.

        " Modify item with new valid to
        <fs_item>-ValidTo = lv_new_valid_to.

        " Read conditions from entity
        READ ENTITIES OF zrk_i_doc_head IN LOCAL MODE
            ENTITY Items BY \_Conds
            FIELDS ( ValidFrom ValidTo )
            WITH VALUE #( ( %tky = <fs_item>-%tky ) )
            RESULT DATA(lt_conds).

            LOOP AT lt_conds ASSIGNING FIELD-SYMBOL(<fs_conds>)
                                    WHERE ValidFrom LE lv_old_valid_to
                                     AND ValidTo GE lv_old_valid_to..

              <fs_conds>-ValidTo = lv_new_valid_to.

            ENDLOOP.

            " Modify conditions entity
            MODIFY ENTITIES OF zrk_i_doc_head IN LOCAL MODE
                ENTITY Conds
                UPDATE FIELDS ( ValidTo )
                WITH CORRESPONDING #( lt_conds ).


      ENDLOOP.

      " Modify Items entity
      MODIFY ENTITIES OF zrk_i_doc_head IN LOCAL MODE
            ENTITY Items
            UPDATE FIELDS ( ValidTo )
            WITH CORRESPONDING #( lt_items ).


    ENDLOOP.

    " Modify header entity
    MODIFY ENTITIES OF zrk_i_doc_head IN LOCAL MODE
        ENTITY Head
        UPDATE
        FIELDS ( ValidTo )
        WITH VALUE #( FOR <fs_doc> IN lt_doc_head
                        ( %tky = <fs_doc>-%tky
                          validTo = COND #( WHEN lv_new_valid_to IS NOT INITIAL
                          THEN lv_new_valid_to
                          ELSE <fs_doc>-ValidTo )  ) )
        REPORTED DATA(lt_update_reported).

    reported = CORRESPONDING #( DEEP lt_update_reported ).

    " Return result to UI
    READ ENTITIES OF zrk_i_doc_head IN LOCAL MODE
        ENTITY Head
        ALL FIELDS
        WITH CORRESPONDING #( keys )
        RESULT lt_doc_head.

    result = VALUE #( FOR <fs_doc_head> IN lt_doc_head ( %tky = <fs_doc_head>-%tky
    %param = <fs_doc_head> ) ).

  ENDMETHOD.

6. Position the Action button on List Report and Object Page using annotations.

  @UI: {

  lineItem: [
      { type: #FOR_ACTION,  dataAction: 'ExtendDoc' , label: 'Extend' , position: 90 } ] ,

  identification : [
      { type: #FOR_ACTION,  dataAction: 'ExtendDoc' , label: 'Extend' , position: 90 } ]
  }

7. Generate the service Binding using OData V4 . [ If you use OData V2, then you have to enrich metadata in fiori app from webide or business studio ]

Service%20binding%20for%20document%20app%20with%20Odata%20V4

Service binding for document app with OData V4

Everything is set and its ready for user action:) Hope it helps in learning advanced ABAP RAP.

 

Assigned tags

      26 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Jagtar singh
      Jagtar singh

      Thanks for detail explanation , It will help a lot for start further extension and gives heads up 🙂 .

      Author's profile photo Prateek Mitter
      Prateek Mitter

      Dear Ramjee, thanks for a great introduction to RAP. Looking forward to more tricks and tips!

      Author's profile photo Oana-Elena Vladescu
      Oana-Elena Vladescu

      Hello Ramjee,

      I am trying to do basically the same thing, but for me it does not work as expected.

      I added a button using @UI.identification and UI.lineItem annotations, that should open a dialog box with input fields.

      I created the abstract entity :

      @EndUserText.label: 'Abstract Entity for Release Information'
      @Metadata.allowExtensions: true
      define abstract entity ZOV_A_SYSTEM_RELEASE {
      system_release : z_release_version;
      }

      and the metadata extension for UI labels:

      @Metadata.layer: #CORE
      annotate entity ZOV_A_SYSTEM_RELEASE with
      {
      @EndUserText.label: 'Release'
      system_release;

      }

       

      I added the action in the Behaviour definition:

      action SelectRelease parameter ZOV_A_SYSTEM_RELEASE;

       

      The result in my app is the following: the dialog box opens, I can see the field maintained in the abstract entity, but no annotations are taken into consideration. No label is displayed. Just the field as written in the entity ( system_release ), not even the description from the data element.

      Any idea what am I missing?

      Author's profile photo ramjee korada
      ramjee korada
      Blog Post Author

      Hi Oana,

      Did you try to refresh the app ? Sometimes metadata reflection on UI takes more time.

      Is it in trail system so that I can have look ?

       

      Best wishes,

      Ramjee Korada

      Author's profile photo Mohandoss Palanisamy
      Mohandoss Palanisamy

      Hello Oana, Ramjee,

      Have you resolved this issue?

      I'm now into the same issue as the metadata entension for End user label not getting reflected on the popup.

      Author's profile photo Aynur Vasbiev
      Aynur Vasbiev

      Hello Oana,

      It is just the version of your Odata binding type, use OData V4 - UI instead of V2

       

      So now its works, and there checkboxes instead of radiobuttons=)

      BR, Aynur

      Author's profile photo ramjee korada
      ramjee korada
      Blog Post Author

      Hi Aynur,

      Thanks for highlighting. I was using V4 for quite sometime and did not realize that others might be using still V2.

      I have updated the blog with this point.

      BR,

      Ramjee

      Author's profile photo Malini M
      Malini M

      Hi Ramjee, This is very interesting. Thanks for the detailed explanation.

      Author's profile photo Daniel Ojados Conesa
      Daniel Ojados Conesa

      Thanks Ramjee for sharing. I'm not getting the popup being shown up although the abstract entity and its metadata is created properly. When triggering the action by pushing the corresponding button, it jumps directly to the behavior implementation where I can see the parameters defined in the abstract entity in blank (obviously 🙂 ) but no popup asks me for the input data.

      Would you have an idea about how I can solve it? I already refresh the system a couple of times 🙂

      Thx

      Author's profile photo Aynur Vasbiev
      Aynur Vasbiev

      Dear Ramjee,

      The popup and entity work fine, but there are some problems caused by changing binding type of my service to OData V4 - UI from V2.

      Those are currency and unit of measure assignments for fields. So the error popup is like this:

      How did manage this? And which data types did you use for that?

      BR, Aynur

       

      Author's profile photo ramjee korada
      ramjee korada
      Blog Post Author

      Hello Aynur,

      This problem is solved when you enter respective Uom ( for quantity ) , Currency for ( Amount ) in object page.

      However, It does not allow me to activate abstract entity with UoM field. 

      Once I added semantics, I am able to see the values entered from the dialog in debugging.

       

      BR,

      Ramjee

      Author's profile photo Aynur Vasbiev
      Aynur Vasbiev

      Hello Ramjee,

      Actually, I had problem with UOM fields using that annotation. In Odata V2 it was ok to use any type of amout (INT4, DEC 15/2), while here with Odata V4 it causes errors, like: invalid type '\TYPE=STRING'.

      Now, based on your screenshot I got that we should use 3 decimals after comma=)

      That worked! Thanks!

      BR, Aynur

      Author's profile photo VIGNESH S V
      VIGNESH S V

      Hi Ramjee,

      Could you please explain, what needs to be added for OData V2 from the UI end ? Please try to provide a screenshot explanation for OData V2.

      Thanks,

      Vignesh.

      Author's profile photo Romina Ganserer
      Romina Ganserer

      Hi Ramjee,

       

      we use OData V2 in our project and changing to Odata V4 is not possible at the time.

      You wrote "If you use OData V2, then you have to enrich metadata in fiori app from webide or business studio". But I can't do this in my annotation file. Can you give an example, how this works?

       

      Thanks, Romina.

      Author's profile photo Venkat Srikantan
      Venkat Srikantan

      I am facing an issue

      When am trying to add an action . it is giving error in service binding  -  Duplicate action external name .

      There is no action with the same name . When am trying to expose the action in Behavior Implementation (Projection of Behavior Definition) . then this error comes, and without that the action button is not available in UI .

      Can you please help me.

       

      Thank you

      Regards

      Venkat Srikantan

      Author's profile photo David Sun
      David Sun

      HI Ramjee

      Thanks for your sharing, I just confused with this development mode, you didn't declare any logic about dialog, how system know it should popup a dialog rather than others?

      Author's profile photo ramjee korada
      ramjee korada
      Blog Post Author

      Hi David,

      As mentioned in step #4, we are using parameters for an action. That means user has to fill the values and hence dialog is opened .

        action extendDoc parameter ZRK_A_Doc_Extend result [1] $self;
      Author's profile photo David Sun
      David Sun

      hi Ramjee

      Could you plz share the detail of the parameters value

      Author's profile photo ramjee korada
      ramjee korada
      Blog Post Author

      Hi David,

      Its there in step #2 and step #3.

      Author's profile photo Muhammed Syed
      Muhammed Syed

      This is a very informative post. Thanks!!!

      What if we want to make a parameter as Mandatory? Do we have to add an annotation to achieve this?

      Author's profile photo Muhammed Syed
      Muhammed Syed

      Found the annotation

      @ObjectModel.mandatory: true
      Author's profile photo Jury Rychko
      Jury Rychko

      Many thanks Ramjee. Your post is very helpful.

      Maybe somebody could answer me. Is it possible to call this action with popup from back-end? I need to fill comment field before save. I'm trying to call this action from determination via EML and action is called, but popup is not showed.

       determination CommentPopup on save { update; create; }
       action extendComment parameter z_comment_ext result [1] $self;
      
      
       METHOD commentpopup.     
          MODIFY ENTITY c_test
           EXECUTE extendComment
           FROM VALUE #( ( %key-uuid = keys[ 1 ]-uuid
                        %param-comments = 'Test' ) )
             REPORTED DATA(edit_reported)
             FAILED DATA(edit_failed)
             MAPPED DATA(edit_mapped).
        ENDMETHOD.
      
        METHOD extendComment .
          
        ENDMETHOD.
      Author's profile photo Vijaya Chintarlapalli
      Vijaya Chintarlapalli

      ramjee korada  : Thanks for useful blog, I have similar requirement to read notes and expose via API instead of displaying in Fiori app. Should i expose abstract entity via action or Function ?

      Author's profile photo Udita Saklani
      Udita Saklani

      Hello ramjee korada,

      We have tried implementing an action by the exact same way as you have mentioned.
      However, the button is coming disabled in our scenario.
      Can you let us know what could be possibly missing here?

      Thanks & Regards,

      Udita Saklani

      Author's profile photo Guilherme Salazar
      Guilherme Salazar

      Hello, ramjee korada,

      Great and very useful explanation!

      However, I have another requirement for a custom action that I was still not able to do:

      Is it possible to open a popup confirmation in a custom action?

      As an example, I have a custom action called "Cancel document", which I want the user confirmation before (Yes/No).

      Is this possible?

      Thanks in advance,

      Guilherme

      Author's profile photo ramjee korada
      ramjee korada
      Blog Post Author

      Hello Guilherme,

      This can be done using Fiori elements application . But I dont think possible at ABAP RAP level .

      https://sapui5.hana.ondemand.com/sdk/#/topic/87130de10c8a44269c605b0322df6b1a

      <Annotations Target="GWSAMPLE_BASIC.GWSAMPLE_BASIC_Entities/RegenerateAllData">
      <Annotation Term="com.sap.vocabularies.Common.v1.IsActionCritical" Bool="true"/>
      </Annotations>

       

      Best wishes,

      Ramjee