One ALV with headers and a second with details of selected row – quite a common use-case. And won’t it be practical to have all this in one screen, so users can check details quickly without constant back and forth between screens? This was indeed what users wanted and what I implemented for them.
In this post, I will describe how to make such a screen with two ALVs, utilizing CL_SALV_TABLE, displaying dependent information.
How to achieve split screen? Splitters and containers!
This screen distribution can be achieved by creating a splitter and two containers. Then place each ALV in its own container. I show it for two, but will work for whatever number you choose.
I do have my own class handling all the ALV-related things, therefore I have these set as instance attributes.
Then, compose everything together in the build_alv method. Notice how I specify the number of requested rows and columns when creating the splitter. When creating each ALV, I specify in which container they should go.
METHOD build_alv.
*<-------------------------------------------
DATA: lr_column_1 TYPE REF TO cl_salv_column_list,
lr_column_2 TYPE REF TO cl_salv_column_list.
DATA: lo_events TYPE REF TO cl_salv_events_table.
* ------------------
* Create ALV screens
TRY.
* Splitter - it is neccessary to specify the default_screen as parent
gr_splitter = NEW #( parent = cl_gui_container=>default_screen
no_autodef_progid_dynnr = abap_true
rows = 2
columns = 1 ).
* Container 1 for header
gr_container_1 = gr_splitter->get_container( row = 1
column = 1 ).
* Container 2 for detail
gr_container_2 = gr_splitter->get_container( row = 2
column = 1 ).
*<< ALV1 - gt_alv_1 is the table with the data
cl_salv_table=>factory( EXPORTING r_container = gr_container_1
IMPORTING r_salv_table = gr_salv_1
CHANGING t_table = gt_alv_1 ).
* Set ALV functions - should you wish to include any
gr_salv_func_1 = gr_salv_1->get_functions( ).
gr_salv_func_1->set_all( abap_true ).
* Set display settings as usual
DATA(lr_display_1) = gr_salv_1->get_display_settings( ).
* Selection - set as usual
gr_salv_1->get_selections( )->set_selection_mode( if_salv_c_selection_mode=>multiple ).
* Layout - set as usual
DATA(ls_key_1) = VALUE salv_s_layout_key( report = sy-cprog
handle = '0001' ).
DATA(lr_layout_1) = gr_salv_1->get_layout( ).
lr_layout_1->set_key( ls_key_1 ).
Now we may proceed to create the second ALV in its own container. The data table may, for example, display the details of the very first row as default option.
*<< ALV_2 - details - gt_alv_2 is the table with data for the second ALV
cl_salv_table=>factory( EXPORTING r_container = gr_container_2
IMPORTING r_salv_table = gr_salv_2
CHANGING t_table = gt_alv_2 ).
* ALV functions
gr_salv_2->get_functions( )->set_all( abap_true ).
* Display settings - set as usual
DATA(lr_display_2) = gr_salv_2->get_display_settings( ).
* Layout - set as usual
DATA(ls_key_2) = VALUE salv_s_layout_key( report = sy-cprog
handle = '0002' ).
How to set column cells clickable? Hotspot and link click event!
Now our screen has correctly set container and we have created the first ALV. We want the column ‘TANUM’ to be clickable and display detail in the second ALV based on these clicks.
To achieve this, we can set this column as having cell type of if_salv_c_cell_type=>hotspot.
* Set columns
* Set hotspot on particular column
DATA(lr_columns_1) = gr_salv_1->get_columns( ).
lr_columns_1->set_optimize( abap_true ).
lr_column_1 ?= lr_columns_1->get_column( 'TANUM' ).
lr_column_1->set_cell_type( if_salv_c_cell_type=>hotspot ).
To detect the event of user clicking on the hotspots, we will register an event handler for the ALV.
* ALV events - the implementation of the on link click event follows further in the post
lo_events = gr_salv_1->get_event( ).
SET HANDLER alv_1_on_link_click FOR lo_events.
And now we just display everything – do mind the write: space part. It will not display correctly if you omit it!
*<< Display ALV_1
gr_salv_1->display( ).
*<< Display ALV_2,
gr_salv_2->display( ).
*<< Have to be to display ALV in full screen mode
WRITE: space.
CATCH cx_salv_msg cx_salv_not_found cx_salv_data_error cx_salv_access_error INTO DATA(lx_alv).
DATA(lv_message) = lx_alv->get_text( ).
raise_sy( ).
ENDTRY.
ENDMETHOD.
And with this the build_alv method is done!
On link click handler method
I have implemented the handler as another method of the class responsible for this whole screen. It has the following signature.
This event handler on its own provides us with the number of the row the user selected. This makes it very easy to work with. We will select the data we wish to have in the second ALV, put them in its data table and refresh everything.
METHOD alv_1_on_link_click.
*<-------------------------------------------
DATA: ls_alv_1 LIKE LINE OF gt_alv_1,
ls_alv_2 LIKE LINE OF gt_alv_2,
ls_data LIKE LINE OF go-data_t,
ls_tai LIKE LINE OF ls_data-tai_t.
* -------------------
*<< Get the data of the selected row and select data for second ALV accordingly to your needs
READ TABLE gt_alv_1 INTO ls_alv_1 INDEX row.
CHECK sy-subrc = 0.
READ TABLE go-data_t INTO ls_data
WITH KEY key_s-tanum = ls_alv_1-tanum.
CHECK sy-subrc = 0.
REFRESH gt_alv_2.
LOOP AT ls_data-tai_t INTO ls_tai.
MOVE-CORRESPONDING ls_tai TO ls_alv_2.
APPEND ls_alv_2 TO gt_alv_2.
ENDLOOP.
gr_salv_1->refresh( ).
* Second ALV will refresh its data based on the changed data table
gr_salv_2->refresh( ).
ENDMETHOD.
And this is it! A simple way to display two ALVs with dependent information based on user selection in one screen.
What about that Edit button?
You may have noticed that my first screenshot also includes Edit and Save buttons. Yes, it is indeed an editable ALV based on CL_SALV_TABLE. And more than that, it works with the changes made by the release 756!
No comments:
Post a Comment