Link Search Menu Expand Document

Screen manager

If you have a global class, how to use screens in it correctly?
According to the SAP recommendation, you can use function groups.
But how convenient is this?

image


ZCL_EUI_SCREEN examples

SE38 -> ZEUI_TEST_SCREEN*

REPORT ztest_screen.

" dynnr = 1000
PARAMETERS:
  p_obl  TYPE i,
  p_gry1 TYPE i,
  p_gry2 TYPE i MODIF ID hid.

AT SELECTION-SCREEN OUTPUT.
  " Rules for SELECTION-SCREEN
  DATA(lo_screen) = NEW zcl_eui_screen( iv_dynnr = '1000' ).

  " Make it OBLIGATORY
  lo_screen->customize( name     = 'P_OBL'
                        required = '1' ).
  " Gray by mask
  lo_screen->customize( name   = 'P_GRY*'
                        input  = '0' ).
  " Hide by SCREEN-GROUP1
  lo_screen->customize( group1    = 'HID'
                        input     = '0'
                        active    = '0'
                        invisible = '1' ).
  " Apply all rules
  lo_screen->pbo( ).

image

REPORT ztest_screen2.

" Screen 1010
SELECTION-SCREEN BEGIN OF SCREEN 1010 AS SUBSCREEN.
SELECTION-SCREEN BEGIN OF BLOCK bl_1010 WITH FRAME TITLE TEXT-tit.
PARAMETERS : p_fld_01 TYPE sytabix,
             p_path   TYPE text255.
SELECTION-SCREEN END OF BLOCK bl_1010.
SELECTION-SCREEN END OF SCREEN 1010.

" If SCREEN in another program pass values
TYPES:
  BEGIN OF ts_context,
    p_fld_01 TYPE sytabix,
    p_path   TYPE text255,
  END OF ts_context.

START-OF-SELECTION.
  " Fill context
  DATA(lr_context) = NEW ts_context( p_fld_01 = 777
                                     p_path   = 'C:\ok.txt' ).
  " Initialize with context
  DATA(lo_screen) = NEW zcl_eui_screen( iv_dynnr   = '1010'
                                        ir_context = lr_context ).
  " Screen options
  lo_screen->customize( it_ = VALUE #(
   ( name = 'P_FLD_01' required = '1' )
   ( name = 'P_PATH'   input    = '0' ) ) ).

  " If pressed OK. For PAI & PBO methods pass IO_HANDLER = ME
  CHECK lo_screen->popup( iv_col_end = 118 )->show( ) = 'OK'.
  MESSAGE 'Ok' TYPE 'S'.

AT SELECTION-SCREEN OUTPUT.
  lo_screen->pbo( ).

image

REPORT zeui_test_screen_02.

" No screen declaration
NEW zcl_eui_screen(
 " Virtual screen number
 iv_dynnr       = zcl_eui_screen=>mc_dynnr-free_sel
 " Pass only context
 ir_context     = NEW ts_context( )

 " Set PAI & PBO handlers (optional)
)->show( io_handler = me ).


" Before ->show( ) method, you can call ->popup( ) or ->set_status( ) methods in a chain form
 
...

*  ME-> should contain
  METHODS:
  " Process commands of STATUS_MANY_BUTTONS
  on_pai_event FOR EVENT pai_event OF zif_eui_manager
    IMPORTING
        sender
        iv_command.
...
  
  METHOD on_pai_event.
    " Who send event ?
    DATA(lo_screen) = CAST zcl_eui_screen( sender ).
    " Get content
    DATA(ls_context) = CAST ts_context( lo_screen->get_context( ) ).

image

Usually, to customize the screen, the developer:

  1. Initializes the screen with data by passing context
    • Filling TABLES: ZSS_SCREEN_0200. for regular screens
    • Filling parameters of SELECTION-SCREEN BEGIN OF SCREEN for selection screens
  2. Performs PBO logic
    • SET PF-STATUS, SET TITLEBAR
    • AT SELECTION-SCREEN OUTPUT. -> pbo( ) -> LOOP AT SCREEN
  3. Next is checking user input
    • AT SELECTION-SCREEN. -> pai( ) -> MESSAGE TYPE 'E'
  4. After the screen show, further processing of the user entered data
    • DATA(lv_value) = ZSS_SCREEN_0200-FIELD_01.

If you use global classes, you probably know the feeling of the archaic nature of this method
We will consider each step separately.


1) Context transfer

Whether it’s web-dynpro, selection or regular screens, it’s most convenient to use a structure to describe the screen.
In it, you can specify the correct data element and text, search helps etc.

That is, you can say the structure is your screen. structure = screen

For the class ZCL_EUI_SCREEN is often sufficient to pass such a structure
It will contain the name of the fields and the initial values.

    " Checked SCREEN context
    BEGIN OF ts_context,
      p_bukrs  TYPE bukrs,
      p_bdc_m  TYPE ettcd_mode, " <-- listbox by domain
      p_mandt  TYPE t001-mandt, " <-- listbox in runtime
      p_check  TYPE xsdboolean,
      s_user   TYPE offline_log_user_itab, " Range <-- cl_ci_query_attributes no SH
      p_land1  TYPE t005t-land1,
      p_fld_i  TYPE syindex,       " do not use i! use from dictionary
      p_fld_i2 TYPE sytabix,       " do not use i! use from dictionary
      " p_memo     TYPE stringval, " String & tables also Ok
    END OF ts_context,

If you just need to pass the initial values to the screen fill ir_context parameter

    DATA(lo_scr_1020) = NEW zcl_eui_screen(
        ir_context = new ts_context( p_bukrs = '1000' )
    ).

For item 4) after closing the screen, through the context you can get the values entered by a user
So actually ir_context works like CHANGING parameter

    DATA(lr_context) = new ts_context( p_bukrs = '1000' ).

    " Context transfer
    DATA(lo_scr_1020) = NEW zcl_eui_screen(
        ir_context = lr_context ).

    " If the user clicked OK
    check lo_scr_1020->show( ) = 'OK'.

    " Get result
    DATA(lv_new_bukrs) = lr_context->p_bukrs.

1.1) Screen number IV_DYNNR

new zcl_eui_screen( iv_dynnr = ) could contain virtual values

If you are familiar with two common SAP techniques,
You do not need to declare the screen through SELECTION-SCREEN BEGIN OF SCREEN in the program, just use:

  • CALL FUNCTION ‘FREE_SELECTIONS_DIALOG’
    • new zcl_eui_screen( iv_dynnr = zcl_eui_screen=>mc_dynnr-free_sel )
  • CL_CI_QUERY_ATTRIBUTES=>GENERIC( )
    • new zcl_eui_screen( iv_dynnr = zcl_eui_screen=>mc_dynnr-dynamic )
  • If you want to use your own screen, already declared in another program. Specify it in the constructor
    • new zcl_eui_screen( iv_dynnr = '1020' iv_cprog = 'ZEUI_TEST_SCREEN_02' )

2) PBO

2.1 To use custom PF-STATUS and TITLEBAR, pass them after the calling the constructor in SET_STATUS method

    " PF-STATUS & SET TITELEBAR 
    DATA(lo_scr_1020) = NEW zcl_eui_screen( iv_dynnr = '1020'
      )->set_status( VALUE #( title = 'Screen title'
                              prog  = sy-cprog
                              name  = 'STATUS_MANY_BUTTONS' ) ).

2.2 LOOP AT SCREEN

Often in PBO this block is quite confusing
On the idea of setting SCREEN through the parameters I saw here https://entropii.net/?p=2927

I hope the meaning of this syntax is clear without explanation, since the parameters correspond to the SCREEN fields

SE38 -> ZEUI_TEST_SCREEN_00

  " Gray
  lo_screen->customize( name = 'P_FLD_01' input = '0' ).

  " Obligatory & change text
  lo_screen->customize(
    name     = 'P_FLD_02'
    required = '1'
    iv_label = 'Make required'  ).

  " Hide by mask
  lo_screen->customize(
    name      = '*P_0*'
    input     = '0'
    active    = '0'
    invisible = '1' ).

  " Hide or show by group
  lo_screen->customize(
    group1    = COND #( WHEN p_radio1 = abap_true THEN 'GR1' ELSE 'GR2' )
    input     = '1'
    active    = '1'
    invisible = '0' ).

    " Set listbox
  lo_screen->customize(
    name       = 'P_MANDT'
    required   = '1'
    iv_label   = 'Client number'
    it_listbox = lt_listbox ).

Also you can pass multiple rules in a one table image

It’s more convenient from ABAP 7.40 syntax image


3) User input validation

Like all child classes of ZCL_EUI_MANAGER handlers for PAI or PBO (if screen->customize( ) is not enough) can be passed to the SHOW method

image

    " Next screen interation
    lv_cmd = lo_screen_main->show(
     io_handler      = lo_handler
     " by default call all handlers (For clarity purpose)
     iv_handlers_map = 'ON_START_PAI' ).

    " Pressed cancel
    IF lv_cmd NP 'CMD_*'.
      RETURN. " Cancel pressed
    ENDIF.

Handler ON_START_PAI accepts the function code IV_COMMAND and can close the current screen CV_CLOSE->* = ‘X’

image

Since all 4 methods have the same signature, the actions they perform are similar
So after closing the screen, the SHOW method always returns the last function code. Often enough to check it for ‘OK’

    " If pressed OK
    CHECK lo_screen->show( ) = 'OK'.

4) Post Processing

About item 4), it has already been written above that the context can be passed (and then received) through the ir_context parameter.
After closing the screen, it will contain the entered data.

    DATA(lo_scr_1020) = NEW zcl_eui_screen(
        ir_context = new ts_context( p_bukrs = '1000' )
    ).

Usually a reference to the local structure is suitable for this.
To get it and read the current context in PAI you need to use the get_context method
But firstly the sender must be converted to ZCL_EUI_SCREEN

METHOD on_start_pai.  
  " Main Screen Structure
  DATA lr_context TYPE REF TO TS_CONTEXT_MAIN.

  " Get access to screen data
  data(lo_screen) = cast ZCL_EUI_SCREEN( sender ).
  lr_context ?= lo_screen->get_context( ).

  " For demo only
  IF lr_context->FIELD_01 IS INITIAL.
    MESSAGE 'Field is initial' TYPE 'S' DISPLAY LIKE 'E'.
    RETURN.
  ENDIF.

  cv_close->* = abap_true.
ENDMETHOD.