2011-12-14

WD Screen Variants - Save Variant

overview

<< previous | next >>

The concept of a selection screen variant is something that most SAP users have come to expect, yet this feature is unavailable in standard Web Dynpro. Below is the next in a series of posts detailing how to bring this necessary feature back to Web Dynpro. Start here to see the full requirements.

Let’s wrap this series up – we’re getting close.  Below is the flow of the Save operation. When the user clicks the button, the BTN_SAVE_CLICK event is fired:

   1: METHOD onactionbtn_save_click .                             " PLM8034
   2:  
   3:   wd_comp_controller->fire_before_save_evt(  ).
   4:   wd_comp_controller->m_clear_msgs = abap_true.
   5:   me->prompt_to_save( ).
   6:  
   7: ENDMETHOD.

The PROMPT_TO_SAVE method then displays the W_SAVE_VARIANT window and waits for the [OK] button.



   1: METHOD prompt_to_save .                                     " PLM8034
   2:  
   3:   DATA: lo_window_manager             TYPE REF TO if_wd_window_manager,
   4:         lo_api_component              TYPE REF TO if_wd_component,
   5:         lo_window                     TYPE REF TO if_wd_window,
   6:         lo_api                        TYPE REF TO if_wd_view_controller.
   7:  
   8:   lo_api = wd_this->wd_get_api( ).
   9:   lo_api_component = wd_comp_controller->wd_get_api( ).
  10:   lo_window_manager = lo_api_component->get_window_manager( ).
  11:  
  12:   wd_comp_controller->refresh_variant_fields( ).
  13:  
  14:   lo_window = lo_window_manager->create_window(
  15:                       window_name               = 'W_SAVE_VARIANT'
  16:                       title                     = 'Save Variant'
  17:                       button_kind               = if_wd_window=>co_buttons_okcancel
  18:                       close_button              = abap_true ).
  19:   lo_window->subscribe_to_button_event(
  20:                       button            = if_wd_window=>co_button_ok
  21:                       action_name       = 'SAVE_OK'
  22:                       action_view       = lo_api
  23:                       is_default_button = abap_true ).
  24:  
  25:   lo_window->open( ).
  26:  
  27: ENDMETHOD.

The neat thing about this selection screen variant implementation is that it offers the user the ability to save dynamic date parameters.  The W_SAVE_VARIANT window uses ALV (usage 2) to display a list of fields for this purpose.  We’ll go into more detail on that in the next post.  For now, let’s focus on saving the variant.


SNAGHTML373aa06


The view V_SAVE_VARIANT shows the variant name and description.  Also available is the ability to “lock” the variant for use only by a single user id.  Finally the list of fields from all attached selection screens.


SNAGHTML3761e7a


Again, the view has an INIT_ALV routine to set up ALV2.  It is called from the WDDOINIT method.  Here’s a better look at the “clear messages” mentioned back in the Get Variant section:



   1: METHOD wddoinit .                                           " PLM8034
   2:  
   3:   wd_this->init_alv( ).
   4:  
   5:   DATA: lr_controller                 TYPE REF TO if_wd_controller,
   6:         lr_msgman                     TYPE REF TO if_wd_message_manager,
   7:         l_msg                         TYPE string.
   8:   IF wd_comp_controller->m_clear_msgs = abap_true.
   9:     lr_controller ?= wd_this->wd_get_api( ).
  10:     lr_msgman = lr_controller->get_message_manager( ).
  11:     lr_msgman->clear_messages( ).
  12:   ENDIF.
  13:  
  14: ENDMETHOD.

After the variant name and description are entered, the user presses the [OK] button.  Once pressed, the MAIN view SAVE_OK action is fired.  In the ONACTIONSAVE_OK routine, we need to check for validity and existence and react accordingly.



   1: METHOD onactionsave_ok .                                    " PLM8034
   2:  
   3:   DATA: l_exists                      TYPE xfeld,
   4:         l_invalid                     TYPE xfeld.
   5:   wd_comp_controller->check_save_variant( IMPORTING: e_invalid = l_invalid
   6:                                                      e_exists = l_exists   ).
   7:  
   8:   IF l_invalid = abap_true.
   9:     wd_comp_controller->m_clear_msgs = abap_false.
  10:     me->prompt_to_save( ).
  11:   ELSEIF l_exists = abap_true.
  12:     me->prompt_overwrite( ).
  13:   ELSE.
  14:     me->save_variant( ).
  15:   ENDIF.
  16:  
  17: ENDMETHOD.

The PROMPT_OVERWRITE routine uses a popup window for user confirmation.



   1: METHOD prompt_overwrite .                                   " PLM8034
   2:  
   3:   DATA: lo_nd_in                      TYPE REF TO if_wd_context_node.
   4:   lo_nd_in = wd_context->get_child_node( name = wd_this->wdctx_in ).
   5:  
   6:   DATA: l_variant_name                TYPE variant.
   7:   lo_nd_in->get_attribute( EXPORTING: name = 'VARIANT_NAME'
   8:                            IMPORTING: value = l_variant_name ).
   9:  
  10:   DATA: lo_window_manager             TYPE REF TO if_wd_window_manager,
  11:         lo_api_component              TYPE REF TO if_wd_component,
  12:         lo_window                     TYPE REF TO if_wd_window,
  13:         lo_api                        TYPE REF TO if_wd_view_controller.
  14:  
  15:   lo_api = wd_this->wd_get_api( ).
  16:   lo_api_component = wd_comp_controller->wd_get_api( ).
  17:   lo_window_manager = lo_api_component->get_window_manager( ).
  18:  
  19:   DATA: lt_msgs                       TYPE string_table,
  20:         l_msg                         TYPE string.
  21:   MESSAGE i627(db) INTO l_msg WITH l_variant_name.
  22:   APPEND l_msg TO lt_msgs.
  23:   MESSAGE i041(sapbc_global) INTO l_msg.
  24:   APPEND l_msg TO lt_msgs.
  25:  
  26:   lo_window = lo_window_manager->create_popup_to_confirm(
  27:                       text                      = lt_msgs
  28:                       window_title              = 'Overwrite Variant?'
  29:                       button_kind               = if_wd_window=>co_buttons_okcancel
  30:                       close_button              = abap_true ).
  31:   lo_window->subscribe_to_button_event(
  32:                       button            = if_wd_window=>co_button_ok
  33:                       action_name       = 'SAVE_CONFIRM'
  34:                       action_view       = lo_api
  35:                       is_default_button = abap_true ).
  36:  
  37:   lo_window->open( ).
  38:  
  39: ENDMETHOD.

After a valid variant name has been identified, the component controller’s SAVE_VARIANT routine does the real work.  First, we update a few header fields: program, variant, change date, etc.  Then we get the field values in GET_FIELDS.  Finally, we save it to storage with the EXPORT TO DATABASE statement.



   1: METHOD save_variant .                                       " PLM8034
   2:  
   3: **********************************************************************
   4: * Used a combination of the following two posts for variants.
   5: * http://www.sdn.sap.com/irj/scn/index?rid=/library/uuid/f028c2b9-1730-2d10-71ae-ce300ea00573
   6: * http://wiki.sdn.sap.com/wiki/display/Snippets/Variant+with+Web+dynpro+application+(+Save+or++Read+)
   7: **********************************************************************
   8:  
   9:   TYPES: BEGIN OF ty_dbkey,
  10:           prog_name                   TYPE zes_wdvari-prog_name,
  11:           vari_name                   TYPE zes_wdvari-vari_name,
  12:          END OF ty_dbkey.
  13:  
  14:   DATA: lr_controller                 TYPE REF TO if_wd_controller,
  15:         lr_msgman                     TYPE REF TO if_wd_message_manager,
  16:         l_msg                         TYPE string.
  17:   lr_controller ?= wd_this->wd_get_api( ).
  18:   lr_msgman = lr_controller->get_message_manager( ).
  19:  
  20:   DATA: lo_nd_in                      TYPE REF TO if_wd_context_node.
  21:   lo_nd_in = wd_context->get_child_node( name = wd_this->wdctx_in ).
  22:  
  23:   DATA: l_repid                       TYPE repid.
  24:   lo_nd_in->get_attribute( EXPORTING: name = 'REPID'
  25:                            IMPORTING: value = l_repid ).
  26:  
  27:   DATA: l_variant_name                TYPE variant.
  28:   lo_nd_in->get_attribute( EXPORTING: name = 'VARIANT_NAME'
  29:                            IMPORTING: value = l_variant_name ).
  30:  
  31:   DATA: ls_wdvari                     TYPE zes_wdvari.
  32:  
  33:   SELECT SINGLE prog_name vari_name protected
  34:                 ename edat etime
  35:                 aename aedat aetime
  36:     INTO CORRESPONDING FIELDS OF ls_wdvari
  37:     FROM zes_wdvari
  38:    WHERE relid = 'WD'
  39:      AND prog_name = l_repid
  40:      AND vari_name = l_variant_name.
  41:   IF sy-subrc = 0.
  42:     ls_wdvari-aename = sy-uname.
  43:     ls_wdvari-aedat = sy-datum.
  44:     ls_wdvari-aetime = sy-uzeit.
  45:   ELSE.
  46:     ls_wdvari-ename = sy-uname.
  47:     ls_wdvari-edat = sy-datum.
  48:     ls_wdvari-etime = sy-uzeit.
  49:   ENDIF.
  50:  
  51:   IF ls_wdvari-protected = abap_true AND
  52:      ls_wdvari-ename NE sy-uname.
  53:     MESSAGE e647(db) INTO l_msg WITH l_variant_name.
  54:     lr_msgman->report_error_message( l_msg ).
  55:     RETURN.
  56:   ENDIF.
  57:  
  58:   lo_nd_in->get_attribute( EXPORTING: name = 'VARIANT_DESC'
  59:                            IMPORTING: value = ls_wdvari-vtext ).
  60:   lo_nd_in->get_attribute( EXPORTING: name = 'PROTECTED'
  61:                            IMPORTING: value = ls_wdvari-protected ).
  62:  
  63:   DATA: lt_values                     TYPE TABLE OF zes_vuvvalues.
  64:   lt_values = me->get_fields( ).
  65:  
  66:   DATA: ls_key                        TYPE ty_dbkey.
  67:   ls_wdvari-prog_name = l_repid.
  68:   ls_wdvari-vari_name = l_variant_name.
  69:   MOVE-CORRESPONDING ls_wdvari TO ls_key.
  70:  
  71:   EXPORT datatable = lt_values
  72:       TO DATABASE zes_wdvari(wd)
  73:     FROM ls_wdvari
  74:       ID ls_key.
  75:  
  76:   IF sy-subrc = 0.
  77:     MESSAGE s617(db) INTO l_msg WITH l_variant_name.
  78:     lr_msgman->report_success( l_msg ).
  79:   ELSE.
  80:     MESSAGE s621(db) INTO l_msg WITH l_variant_name.
  81:     lr_msgman->report_error_message( l_msg ).
  82:   ENDIF.
  83:  
  84: ENDMETHOD.

The GET_FIELDS routine has the job of retrieving all field values from all attached selection screens.



   1: METHOD get_fields .                                         " PLM8034
   2:  
   3:   DATA: lo_selopt                     TYPE REF TO if_wd_select_options.
   4:   DATA: lt_fields                     TYPE if_wd_select_options=>tt_selection_screen_item,
   5:         ls_field                      LIKE LINE OF lt_fields.
   6:   DATA: lt_all_fields                 LIKE lt_fields.
   7:   DATA: lr_param_value                TYPE REF TO data.
   8:   DATA: lt_range_table                TYPE REF TO data.
   9:   FIELD-SYMBOLS: <l_param_value>      TYPE ANY.
  10:   FIELD-SYMBOLS: <lt_range_table>     TYPE STANDARD TABLE.
  11:   FIELD-SYMBOLS: <ls_range>           TYPE ANY.
  12:   FIELD-SYMBOLS: <ls_field>           LIKE LINE OF rt_result.
  13:  
  14:   CLEAR: lt_all_fields[].
  15:  
  16:   LOOP AT wd_assist->selopt_screens INTO lo_selopt.
  17:  
  18:     CLEAR: lt_fields.
  19:     lo_selopt->get_parameter_fields( IMPORTING et_fields = lt_fields ).
  20:     LOOP AT lt_fields INTO ls_field.
  21:       lr_param_value = lo_selopt->get_value_of_parameter_field( ls_field-m_id ).
  22:       ASSIGN lr_param_value->* TO <l_param_value>.
  23:       CHECK sy-subrc = 0.
  24:  
  25:       APPEND INITIAL LINE TO rt_result ASSIGNING <ls_field>.
  26:       <ls_field>-paramid = ls_field-m_id.
  27:       <ls_field>-kind = 'P'.
  28:       <ls_field>-sign = 'I'.
  29:       <ls_field>-option = 'EQ'.
  30:       <ls_field>-low = <l_param_value>.
  31:       wd_this->get_field_params( CHANGING ct_field = <ls_field> ).
  32:  
  33:     ENDLOOP.
  34:  
  35:     CLEAR: lt_fields.
  36:     lo_selopt->get_selection_fields( IMPORTING et_fields = lt_fields ).
  37:     LOOP AT lt_fields INTO ls_field.
  38:       lt_range_table = lo_selopt->get_range_table_of_sel_field( ls_field-m_id ).
  39:       ASSIGN lt_range_table->* TO <lt_range_table>.
  40:       CHECK sy-subrc = 0.
  41:  
  42:       LOOP AT <lt_range_table> ASSIGNING <ls_range>.
  43:         APPEND INITIAL LINE TO rt_result ASSIGNING <ls_field>.
  44:         <ls_field>-paramid = ls_field-m_id.
  45:         <ls_field>-kind = 'S'.
  46:         MOVE-CORRESPONDING <ls_range> TO <ls_field>.
  47:         wd_this->get_field_params( CHANGING ct_field = <ls_field> ).
  48:       ENDLOOP.
  49:  
  50:     ENDLOOP.
  51:  
  52:   ENDLOOP.
  53:  
  54: ENDMETHOD.

The last couple routines that get called are:



  • REFRESH_VARIANT_LIST – so that the Get Variant screen is up-to-date.
  • (Optionally) FIRE_AFTER_SAVE_EVT – to let the calling application know that a variant has just been saved.

That’s all there is to saving a selection screen variant in Web Dynpro!






overview

<< previous | next >>

No comments:

Post a Comment