2011-08-15

WD Screen Variants - Get 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.

Here is the flow of the Get operation. This is where it starts to get fun.

When the user clicks the button, the BTN_GET_CLICK event is fired.  This event creates an instance of the W_GET_VARIANT window and also assigns the [OK] button to the GET_OK action before opening the window.

   1: METHOD onactionbtn_get_click .                              " 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:   lo_window = lo_window_manager->create_window(
  13:                       window_name               = 'W_GET_VARIANT'
  14:                       title                     = 'Get Variant'
  15:                       button_kind               = if_wd_window=>co_buttons_okcancel
  16:                       close_button              = abap_false ).
  17:   lo_window->subscribe_to_button_event(
  18:                       button            = if_wd_window=>co_button_ok
  19:                       action_name       = 'GET_OK'
  20:                       action_view       = lo_api
  21:                       is_default_button = abap_true ).
  22:   " set up to get variant with user selects row
  23: *  lo_window->subscribe_to_button_event(
  24: *                      button            = if_wd_window=>co_button_close
  25: *                      action_name       = 'GET_OK'
  26: *                      action_view       = lo_api
  27: *                      is_default_button = abap_false ).
  28:  
  29:   wd_comp_controller->mo_get_window = lo_window.
  30:   wd_comp_controller->m_clear_msgs = abap_true.
  31:   lo_window->open( ).
  32:  
  33: ENDMETHOD.

As you can see – I toyed with trying to allow the row selection to cause GET_OK event to fire.  Unfortunately – I didn’t have enough time to make it function properly.  I’m open to suggestions.  I’d like to include it next time around.


The W_GET_VARIANT window utilizes the V_GET_VARIANT view.  The view itself contains only one element: a ViewContainerUIElement named VIEW_LIST.  This is one of our WD ALV grids, so within W_GET_VARIANT we need to embed ALV1 into the VIEW_LIST container.


W_GET_VARIANT Window


Now inside the view, there’s a lot of work to be done to set up the list. I created a method INIT_ALV to help with this. It’s job is to create the usage of the ALV1 component and then configure the ALV for a minimalist view of the variants retrieved by the Component Controller during initialization.



   1: METHOD init_alv .                                           " PLM8034
   2:  
   3:   " http://forums.sdn.sap.com/thread.jspa?threadID=1681440
   4:  
   5:   DATA: lo_cmp_usage                  TYPE REF TO if_wd_component_usage.
   6:   DATA: lr_salv_wd_table              TYPE REF TO iwci_salv_wd_table.
   7:   DATA: lr_column_settings            TYPE REF TO if_salv_wd_column_settings,
   8:         lr_table_settings             TYPE REF TO if_salv_wd_table_settings,
   9:         lr_std_fxns                   TYPE REF TO if_salv_wd_std_functions,
  10:         lr_column                     TYPE REF TO cl_salv_wd_column,
  11:         lt_columns                    TYPE salv_wd_t_column_ref,
  12:         ls_column                     TYPE salv_wd_s_column_ref.
  13:   DATA: lr_col_header                 TYPE REF TO cl_salv_wd_column_header.
  14:   DATA: l_text                        TYPE string.
  15:  
  16: *create an instance of ALV component
  17:   lo_cmp_usage = wd_this->wd_cpuse_alv1( ).
  18: * if not initialized, then initialize
  19:   IF lo_cmp_usage->has_active_component( ) IS INITIAL.
  20:     lo_cmp_usage->create_component( ).
  21:   ENDIF.
  22:  
  23: * get ALV component
  24:   lr_salv_wd_table = wd_this->wd_cpifc_alv1( ).
  25:  
  26:   lr_table_settings ?= lr_salv_wd_table->get_model( ).
  27:   "lr_table_settings->set_enabled( abap_false ).
  28:   "lr_table_settings->set_footer_visible( '01' ).
  29:  
  30:   lr_std_fxns ?= lr_salv_wd_table->get_model( ).
  31:   lr_std_fxns->set_pdf_allowed( abap_false ).
  32:   lr_std_fxns->set_display_settings_allowed( abap_false ).
  33:   lr_std_fxns->set_dialog_settings_allowed( abap_false ).
  34:   lr_std_fxns->set_view_list_allowed( abap_false ).
  35:  
  36:   DATA: lr_checkbox_field             TYPE REF TO cl_salv_wd_uie_checkbox.
  37:  
  38:   lr_column_settings ?= lr_salv_wd_table->get_model( ).
  39:   lt_columns = lr_column_settings->get_columns( ).
  40:   LOOP AT lt_columns INTO ls_column.
  41:     lr_col_header = ls_column-r_column->get_header( ).
  42:  
  43:     CASE ls_column-id.
  44:       WHEN 'VARI_NAME' OR 'ENAME' OR 'AENAME' OR 'VTEXT'.
  45:  
  46:       WHEN 'PROTECTED'.
  47:         lr_col_header->set_prop_ddic_binding_field( value = if_salv_wd_c_ddic_binding=>ddic_bind_none ).
  48:         l_text = wd_assist->if_wd_component_assistance~get_text( '005' ).
  49:         lr_col_header->set_text( l_text ).
  50:  
  51:         CREATE OBJECT lr_checkbox_field
  52:           EXPORTING
  53:             checked_fieldname = ls_column-id.
  54:         ls_column-r_column->set_cell_editor( lr_checkbox_field ).
  55:  
  56:       WHEN OTHERS.
  57:         ls_column-r_column->set_visible( if_wdl_core=>visibility_none ).
  58:     ENDCASE.
  59:  
  60:   ENDLOOP.
  61:  
  62: ENDMETHOD.

INIT_ALV is called from the WDDOINIT of V_GET_VARIANT.  WDDOINIT also uses a public variable set at the Component Controller level to determine whether to clear messages.  This was useful in that if the source selection screen contains required input values, any error messages displayed during validation would not get replicated in this pop-up window.  Using m_clear_msgs variable, though, allows flexibility to display any error messages that you might want to display (example: during the Save operation if the user fails to enter a variant name).



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

After we’ve configured the variant list, we’re finished with the V_GET_VARIANT view.  The rest happens outside this view after the user clicks [OK].  Remember that the [OK] button is mapped to the GET_OK action.  So when ONACTIONGET_OK is called, there are three things to do:



  1. Get the selected variant
  2. Load the variant into the WD selection screen
  3. (Optionally) fire an ‘after get’ event

To get the selected variant, we need to retrieve the variant name from the first selected entry in the variant list.  I then load them into my ‘IN’ node for downstream processing.



   1: METHOD get_selected_variant .                               " PLM8034
   2:  
   3:   DATA: lo_nd_list                    TYPE REF TO if_wd_context_node.
   4:   lo_nd_list = wd_context->get_child_node( name = wd_this->wdctx_variant_list ).
   5:  
   6:   DATA: ls_wdvari                     TYPE zes_wdvari.
   7:   CLEAR: ls_wdvari.
   8:  
   9:   DATA: lt_elements                   TYPE wdr_context_element_set,
  10:         lr_element                    TYPE REF TO if_wd_context_element.
  11:   lt_elements = lo_nd_list->get_selected_elements( abap_true ).
  12:   LOOP AT lt_elements INTO lr_element.
  13:     lr_element->get_attribute( EXPORTING: name = 'VARI_NAME'
  14:                                IMPORTING: value = ls_wdvari-vari_name ).
  15:     lr_element->get_attribute( EXPORTING: name = 'VTEXT'
  16:                                IMPORTING: value = ls_wdvari-vtext ).
  17:     lr_element->get_attribute( EXPORTING: name = 'PROTECTED'
  18:                                IMPORTING: value = ls_wdvari-protected ).
  19:     EXIT.
  20:   ENDLOOP.
  21:  
  22:   DATA: lo_nd_in                      TYPE REF TO if_wd_context_node.
  23:   lo_nd_in = wd_context->get_child_node( name = wd_this->wdctx_in ).
  24:  
  25:   lo_nd_in->set_attribute( EXPORTING: name = 'VARIANT_NAME'
  26:                                       value = ls_wdvari-vari_name ).
  27:   lo_nd_in->set_attribute( EXPORTING: name = 'VARIANT_DESC'
  28:                                       value = ls_wdvari-vtext ).
  29:   lo_nd_in->set_attribute( EXPORTING: name = 'PROTECTED'
  30:                                       value = ls_wdvari-protected ).
  31:  
  32:   r_result = ls_wdvari-vari_name.
  33:  
  34: ENDMETHOD.

The LOAD_VARIANT method exists at the Component Controller level.  It’s job is to retrieve the variant details and set these values into the WD selection screen.



   1: METHOD load_variant .                                       " PLM8034
   2: **********************************************************************
   3: * Used a combination of the following two posts for variants.
   4: * http://www.sdn.sap.com/irj/scn/index?rid=/library/uuid/f028c2b9-1730-2d10-71ae-ce300ea00573
   5: * http://wiki.sdn.sap.com/wiki/display/Snippets/Variant+with+Web+dynpro+application+(+Save+or++Read+)
   6: **********************************************************************
   7:  
   8:   TYPES: BEGIN OF ty_dbkey,
   9:           prog_name                   TYPE zes_wdvari-prog_name,
  10:           vari_name                   TYPE zes_wdvari-vari_name,
  11:          END OF ty_dbkey.
  12:  
  13:   DATA: lo_nd_in                      TYPE REF TO if_wd_context_node.
  14:   lo_nd_in = wd_context->get_child_node( name = wd_this->wdctx_in ).
  15:  
  16:   DATA: l_repid                       TYPE repid.
  17:   lo_nd_in->get_attribute( EXPORTING: name = 'REPID'
  18:                            IMPORTING: value = l_repid ).
  19:  
  20:   DATA: l_variant_name                TYPE variant.
  21:   lo_nd_in->get_attribute( EXPORTING: name = 'VARIANT_NAME'
  22:                            IMPORTING: value = l_variant_name ).
  23:  
  24:   DATA: ls_key                        TYPE ty_dbkey.
  25:   ls_key-prog_name = l_repid.
  26:   ls_key-vari_name = l_variant_name.
  27:  
  28:   IMPORT datatable = rt_values
  29:     FROM DATABASE zes_wdvari(wd)
  30:       ID ls_key.
  31:  
  32:   me->set_fields( rt_values ).
  33:   me->refresh_variant_fields( rt_values ).
  34:  
  35: ENDMETHOD.

We’re about to get into the nuts and bolts of this whole thing.  Retrieving the details is as easy as the IMPORT FROM DATABASE statement above.  In order to set the details into the WD selection screen is a little more involved – the SET_FIELDS method is here for that.  For each selection screen assigned, I get the parameter fields and assign those values, and then work with the selection fields.  The work in both cases is very similar:



  • Check if anything is assigned for this field in the variant.
  • If so, then change the assignment in the field.
  • If not, then make sure the field is set to INITIAL.

There is one additional helper routine SET_FIELD_PARAMS that provides support for dynamic dates.  We’ll get to that in a later post.



   1: METHOD set_fields .                                         " PLM8034
   2:  
   3:   DATA: lo_selopt                     TYPE REF TO cl_wdr_select_options,
   4:         li_selopt                     TYPE REF TO if_wd_select_options.
   5:   DATA: lt_fields                     TYPE if_wd_select_options=>tt_selection_screen_item,
   6:         ls_field                      LIKE LINE OF 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:   DATA: lt_values                     LIKE it_values,
  13:         ls_value                      LIKE LINE OF it_values.
  14:   DATA: lr_value_field_descr          TYPE REF TO cl_abap_elemdescr.
  15:   DATA: ls_rng_date                   TYPE rsdatrange.
  16:  
  17:   LOOP AT wd_assist->selopt_screens INTO li_selopt.
  18:     lo_selopt ?= li_selopt.
  19:  
  20:     CLEAR: lt_fields.
  21:     li_selopt->get_parameter_fields( IMPORTING et_fields = lt_fields ).
  22:     LOOP AT lt_fields INTO ls_field.
  23:       lr_param_value = li_selopt->get_value_of_parameter_field( i_id = ls_field-m_id ).
  24:  
  25:       CLEAR: ls_value.
  26:       ls_value-paramid = ls_field-m_id.
  27:       READ TABLE it_values INTO ls_value WITH KEY paramid = ls_value-paramid.
  28:  
  29:       IF ls_value-low IS NOT INITIAL.
  30:         IF lr_param_value IS INITIAL.
  31:           CREATE DATA lr_param_value TYPE tvarv_low.
  32:         ENDIF.
  33:         ASSIGN lr_param_value->* TO <l_param_value>.
  34:         IF ls_value-vname IS INITIAL.
  35:           <l_param_value> = ls_value-low.
  36:         ELSE.
  37:           ls_rng_date = wd_this->set_field_params( ls_value ).
  38:           <l_param_value> = ls_rng_date-low.
  39:         ENDIF.
  40:         li_selopt->set_value_of_parameter_field( EXPORTING: i_id = ls_field-m_id
  41:                                                             i_value = lr_param_value ).
  42:       ELSEIF lr_param_value IS NOT INITIAL.
  43:         FREE lr_param_value.
  44:         li_selopt->set_value_of_parameter_field( EXPORTING: i_id = ls_field-m_id
  45:                                                             i_value = lr_param_value ).
  46:       ELSE.
  47:         " both are initial - no change
  48:       ENDIF.
  49:  
  50:       " Work around until we implement this OSS note...
  51:       " https://service.sap.com/sap/support/notes/1521366
  52:       " 'render_delta' in between each item in the PARAMETER list because the
  53:       " 'get_value_of_parameter_field' call at the top of the loop is overwriting
  54:       " values changed with 'set_value_of_parameter_field'.
  55:       lo_selopt->render_delta( abap_false ).
  56:  
  57:     ENDLOOP.
  58:  
  59:     CLEAR: lt_fields.
  60:     li_selopt->get_selection_fields( IMPORTING et_fields = lt_fields ).
  61:     LOOP AT lt_fields INTO ls_field.
  62:  
  63:       lt_range_table = li_selopt->get_range_table_of_sel_field( ls_field-m_id ).
  64:       "lt_range_table = lo_selopt->if_wd_select_options~get_range_table_of_sel_field( ls_field-m_id ).
  65:       ASSIGN lt_range_table->* TO <lt_range_table>.
  66:  
  67:       ls_value-paramid = ls_field-m_id.
  68:       lt_values[] = it_values[].
  69:       DELETE lt_values WHERE paramid NE ls_value-paramid.
  70:  
  71:       IF LINES( lt_values[] ) > 0.
  72:         CLEAR: <lt_range_table>[].
  73:  
  74:         READ TABLE lt_values INTO ls_value INDEX 1.
  75:         IF ls_value-vname IS INITIAL.
  76:           LOOP AT lt_values INTO ls_value.
  77:             APPEND INITIAL LINE TO <lt_range_table>[] ASSIGNING <ls_range>.
  78:             MOVE-CORRESPONDING ls_value TO <ls_range>.
  79:           ENDLOOP.
  80:         ELSE.
  81:           APPEND INITIAL LINE TO <lt_range_table>[] ASSIGNING <ls_range>.
  82:           <ls_range> = wd_this->set_field_params( ls_value ).
  83:         ENDIF.
  84:         li_selopt->set_range_table_of_sel_field( EXPORTING: i_id = ls_field-m_id
  85:                                                   it_range_table = lt_range_table ).
  86:       ELSEIF LINES( <lt_range_table>[] ) > 0.
  87:         li_selopt->reset_selection_field( ls_field-m_id ).
  88:       ELSE.
  89:         " both are initial - no change
  90:       ENDIF.
  91:  
  92:     ENDLOOP.
  93:  
  94:     lo_selopt->render_delta( abap_false ).
  95:  
  96:   ENDLOOP.
  97:  
  98: ENDMETHOD.

The REFRESH_VARIANT_FIELDS routine could more properly be thought of as part of the Save Variant process, but it happens during Get Variant only because the data is currently in memory.  It collects meta data about the fields and prepares the field list that is to be displayed in the V_SAVE_VARIANT view.  More on that later.



   1: METHOD refresh_variant_fields.                              " PLM8034
   2:  
   3:   DATA: lr_nd_fields                  TYPE REF TO if_wd_context_node.
   4:   DATA: lt_elements                   TYPE wdr_context_element_set.
   5:   lr_nd_fields = wd_context->get_child_node( name = wd_this->wdctx_variant_fields ).
   6:   lt_elements = lr_nd_fields->get_elements( ).
   7:  
   8:   CHECK LINES( lt_elements ) = 0 OR   " 1st time field list generated
   9:         LINES( it_params ) > 0.       " variant was picked - regenerate list
  10:  
  11:   DATA: li_selopt                     TYPE REF TO if_wd_select_options.
  12:   DATA: lt_fields                     TYPE if_wd_select_options=>tt_selection_screen_item,
  13:         ls_field                      LIKE LINE OF lt_fields.
  14:   DATA: lt_variant_fields             TYPE TABLE OF zes_vuvvalues_alv,
  15:         ls_variant_field              TYPE zes_vuvvalues_alv,
  16:         ls_value                      TYPE zes_vuvvalues.
  17:   DATA: lr_param_value                TYPE REF TO data,
  18:         lr_range_table                TYPE REF TO data,
  19:         lr_range_line                 TYPE REF TO data.
  20:   FIELD-SYMBOLS: <l_value>            TYPE ANY,
  21:                  <lt_range_table>     TYPE ANY TABLE,
  22:                  <ls_range_line>      TYPE ANY.
  23:   DATA: l_kind                        TYPE abap_typekind.
  24:  
  25:   LOOP AT wd_assist->selopt_screens INTO li_selopt.
  26:  
  27:     CLEAR: lt_fields.
  28:     li_selopt->get_parameter_fields( IMPORTING et_fields = lt_fields ).
  29:     LOOP AT lt_fields INTO ls_field.
  30:       CLEAR: ls_variant_field.
  31:       ls_variant_field-paramid = ls_field-m_id.
  32:       ls_variant_field-kind = 'P'.
  33:       ls_variant_field-fieldtext = ls_field-m_description.
  34:  
  35:       READ TABLE it_params INTO ls_value WITH KEY paramid = ls_variant_field-paramid.
  36:       IF sy-subrc = 0.
  37:         MOVE-CORRESPONDING ls_value TO ls_variant_field.
  38:         wd_this->replace_varivar_text( CHANGING cs_value = ls_variant_field ).
  39:       ENDIF.
  40:  
  41:       lr_param_value = li_selopt->get_value_of_parameter_field( i_id = ls_field-m_id ).
  42:       CLEAR l_kind.
  43:       IF lr_param_value IS NOT INITIAL.
  44:         l_kind = cl_abap_elemdescr=>get_data_type_kind( lr_param_value ).
  45:       ENDIF.
  46:       IF l_kind NE cl_abap_elemdescr=>typekind_date.
  47:         ls_variant_field-ronly_dyndate = abap_true.
  48:       ELSE.
  49:         ls_variant_field-edit_dyndate = abap_true.
  50:       ENDIF.
  51:  
  52:       APPEND ls_variant_field TO lt_variant_fields.
  53:     ENDLOOP.
  54:  
  55:     CLEAR: lt_fields.
  56:     li_selopt->get_selection_fields( IMPORTING et_fields = lt_fields ).
  57:     LOOP AT lt_fields INTO ls_field.
  58:       CLEAR: ls_variant_field.
  59:       ls_variant_field-paramid = ls_field-m_id.
  60:       ls_variant_field-kind = 'S'.
  61:       ls_variant_field-fieldtext = ls_field-m_description.
  62:  
  63:       READ TABLE it_params INTO ls_value WITH KEY paramid = ls_variant_field-paramid.
  64:       IF sy-subrc = 0.
  65:         MOVE-CORRESPONDING ls_value TO ls_variant_field.
  66:         wd_this->replace_varivar_text( CHANGING cs_value = ls_variant_field ).
  67:       ENDIF.
  68:  
  69:       lr_range_table = li_selopt->get_range_table_of_sel_field( ls_field-m_id ).
  70:       ASSIGN lr_range_table->* TO <lt_range_table>.
  71:       CREATE DATA lr_range_line LIKE LINE OF <lt_range_table>.
  72:       ASSIGN lr_range_line->* TO <ls_range_line>.
  73:       ASSIGN COMPONENT 'LOW' OF STRUCTURE <ls_range_line> TO <l_value>.
  74:       CLEAR l_kind.
  75:       l_kind = cl_abap_elemdescr=>get_data_type_kind( <l_value> ).
  76:       IF l_kind NE cl_abap_elemdescr=>typekind_date.
  77:         ls_variant_field-ronly_dyndate = abap_true.
  78:       ELSE.
  79:         ls_variant_field-edit_dyndate = abap_true.
  80:       ENDIF.
  81:  
  82:       APPEND ls_variant_field TO lt_variant_fields.
  83:     ENDLOOP.
  84:  
  85:   ENDLOOP.
  86:  
  87:   lr_nd_fields->bind_table( lt_variant_fields ).
  88:  
  89: ENDMETHOD.

The last thing that happens in the Get Variant [OK] button event is to fire the Component Controller’s public AFTER_GET event.  This allows other applications to perform additional processing after the variant details have been set into the selection screen.


That finishes out retrieving the variant.  Next I’ll discuss the routines involved in saving.


 





overview

<< previous | next >>

2011-08-13

WD Screen Variants – Main View

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.

The MAIN view has a very simple layout.  Drop three Web Dynpro buttons on the view, named as shown below.

MAIN view layout

All of the real work in the MAIN view happens in the Methods.

MAIN methods

The flow is essentially the same for each button on the Layout, with some minor differences between them.

  1. Each button is assigned an action: ONACTIONBTN_GET_CLICK, ONACTIONBTN_SAVE_CLICK, and ONACTIONBTN_DELETE_CLICK.
  2. The button click event then creates an instance of a window: W_GET_VARIANT (for Get and Delete) or W_SAVE_VARIANT (for Save).  The [OK] button of the window is assigned to another event: ONACTIONGET_OK, ONACTIONSAVE_OK, and ONACTIONDELETE_OK.
  3. In the case of the Save and Delete operations, a confirmation window may be displayed in which a second [OK] button is tied to an event: ONACTIONSAVE_CONFIRM and ONACTIONDELETE_CONFIRM.
  4. Following all the user interaction and validation the requested operation is executed at the Component Controller level.

In the next post, I’ll detail my implementation of the Get Variant process flow.

overview

<< previous | next >>

2011-06-09

WD Screen Variants – WD Component

overview

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.
ZES_SELOPT_VARIANT
Start your development by creating a new Web Dynpro component named ZES_SELOPT_VARIANT. This WD component will have a public interface with a few methods used to initialize the report name and selection screens. It will have one main window that contains three buttons (by default): Get Variant, Save Variant, and Delete Variant. 
ZES_SELOPT_VARIANTIn the Web Dynpro component, we’ll need to use two instances of the Web Dynpro ALV component:

Comp. Use Component Description
ALV1 SALV_WD_TABLE List of existing selection screen variants for this Web Dynpro application)
ALV2 SALV_WD_TABLE List of fields assigned to this set of selection screens.
This is also where you identify the assistance class created earlier.
In the Component Controller, add the following context nodes:
Node: TEXT stores the values of various labels used through the component.
Context node TEXT
Node: IN stores values that are bound to various screen elements throughout.  This elements in this node could have used a little more structure – maybe split out by view - given the time.
Context node IN
Node: VARIANT_LIST is a table of variants associated with the REPORT_NAME assigned when the component is initialized.
Context node VARIANT_LIST
Node: VARIANT_FIELDS holds a table of fields associated with the currently selected (or newly created) variant.
Context node VARIANT_FIELDS
Node: FIELD_PARAMS is a single-line structure that holds the values selected by the user from view V_ASK_PARAMETERS that are used to help determine dynamic dates (more later).
Context node FIELD_PARAMS
One additional attribute is required on the Component Controller: M_CLEAR_MSGS.  This value will be set at each *first* display of the W_GET_VARIANT and W_SAVE_VARIANT windows in order to prevent ‘required field’ warnings from being shown to the user.  The MO_GET_WINDOW is not used.  It was added as part of an attempt to get the W_GET_VARIANT window to auto-close when a row is selected.
Component controller Attributes
I added the following events to the Component Controller:
Component controller Events
The following methods were added as part of the Web Dynpro Component interface in order of importance:
SET_REPORT_NAME:  Here we’re simply setting the the context node element to remember the value.
   1: METHOD set_report_name .                                    " PLM8034
   2:  
   3:   DATA: lo_nd_in                      TYPE REF TO if_wd_context_node.
   4:   DATA: lo_ni_in                      TYPE REF TO if_wd_context_node_info.
   5:   lo_nd_in = wd_context->get_child_node( name = wd_this->wdctx_in ).
   6:   lo_ni_in = lo_nd_in->get_node_info( ).
   7:  
   8:   lo_nd_in->set_attribute( EXPORTING: name = 'REPID'
   9:                                       value = i_report_name ).
  10:   me->refresh_variant_list( ).
  11:  
  12: ENDMETHOD.

It’s also important to know what the REFRESH_VARIANT_LIST routine is doing. It’s called when the report name is set in addition to a couple of other important times. This retrieves a list of variants from the transparent table created for storing the variants for the report name indicated above.  It binds this list to the VARIANT_LIST context node.

 

   1: METHOD refresh_variant_list .                               " PLM8034
   2:  
   3:   DATA: lo_nd_in                      TYPE REF TO if_wd_context_node.
   4:   DATA: lo_ni_in                      TYPE REF TO if_wd_context_node_info.
   5:   lo_nd_in = wd_context->get_child_node( name = wd_this->wdctx_in ).
   6:   lo_ni_in = lo_nd_in->get_node_info( ).
   7:  
   8:   DATA: l_repid                       TYPE repid.
   9:   lo_nd_in->get_attribute( EXPORTING: name = 'REPID'
  10:                            IMPORTING: value = l_repid ).
  11:  
  12:   DATA: lt_variants                   TYPE TABLE OF zes_wdvari,
  13:         ls_variant                    LIKE LINE OF lt_variants.
  14:   SELECT prog_name vari_name vtext protected
  15:          ename edat etime aename aedat aetime
  16:     INTO CORRESPONDING FIELDS OF TABLE lt_variants
  17:     FROM zes_wdvari
  18:    WHERE relid = 'WD'
  19:      AND prog_name = l_repid.
  20:  
  21:   DATA: lo_nd_list                    TYPE REF TO if_wd_context_node.
  22:   DATA: lo_ni_list                    TYPE REF TO if_wd_context_node_info.
  23:   lo_nd_list = wd_context->get_child_node( name = wd_this->wdctx_variant_list ).
  24:   lo_ni_list = lo_nd_list->get_node_info( ).
  25:  
  26:   lo_nd_list->bind_table( lt_variants ).
  27:  
  28: ENDMETHOD.


APPEND_SELOPT_SCREEN: Add the value supplied to the list of selection screens to process later when getting/saving the variant.


 

   1: METHOD append_selopt_screen .                               " PLM8034
   2:   APPEND i_selopt_screen TO wd_assist->selopt_screens[].
   3: ENDMETHOD.

SHOW_BUTTONS: Show/hide Get/Save/Delete buttons (untested)

 

   1: METHOD show_buttons .                                       " 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:   lo_nd_in->set_attribute( EXPORTING: name = 'VISIBLE_BTN_GET'
   7:                                       value = i_btn_get ).
   8:   lo_nd_in->set_attribute( EXPORTING: name = 'VISIBLE_BTN_SAVE'
   9:                                       value = i_btn_save ).
  10:   lo_nd_in->set_attribute( EXPORTING: name = 'VISIBLE_BTN_DELETE'
  11:                                       value = i_btn_delete ).
  12:  
  13: ENDMETHOD.

GET_VARIANT_NAME: Get variant name chosen by user (untested)


 

   1: METHOD get_variant_name .                                   " 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:   lo_nd_in->get_attribute( EXPORTING: name = 'VARIANT_NAME'
   7:                            IMPORTING: value = r_result ).
   8:  
   9:  
  10: ENDMETHOD.

The WDDOINIT method is called immediately at initialization.  First, I’m initializing the list of ‘dynamic date’ routines used later for DATS fields.  Then I’m setting the labels for various controls used through the views based on logon language.  Finally, I indicate that the MAIN view should show all three buttons by default.


 

   1: METHOD wddoinit .                                           " PLM8034
   2:  
   3:   wd_assist->init_varivar_table( ).
   4:  
   5:   DATA: lo_nd_text                    TYPE REF TO if_wd_context_node.
   6:   lo_nd_text = wd_context->get_child_node( name = wd_this->wdctx_text ).
   7:  
   8:   DATA: l_text                        TYPE string.
   9:  
  10:   l_text = wd_assist->get_text( '001' ).
  11:   lo_nd_text->set_attribute( EXPORTING: name = 'GET'
  12:                                         value = l_text ).
  13:  
  14:   l_text = wd_assist->get_text( '002' ).
  15:   lo_nd_text->set_attribute( EXPORTING: name = 'SAVE'
  16:                                         value = l_text ).
  17:  
  18:   l_text = wd_assist->get_text( '003' ).
  19:   lo_nd_text->set_attribute( EXPORTING: name = 'OK'
  20:                                         value = l_text ).
  21:  
  22:   l_text = wd_assist->get_text( '004' ).
  23:   lo_nd_text->set_attribute( EXPORTING: name = 'CANCEL'
  24:                                         value = l_text ).
  25:  
  26:   l_text = wd_assist->get_text( '005' ).
  27:   lo_nd_text->set_attribute( EXPORTING: name = 'PROTECTED'
  28:                                         value = l_text ).
  29:  
  30:   l_text = wd_assist->get_text( '006' ).
  31:   lo_nd_text->set_attribute( EXPORTING: name = 'PARAM1'
  32:                                         value = l_text ).
  33:  
  34:   l_text = wd_assist->get_text( '007' ).
  35:   lo_nd_text->set_attribute( EXPORTING: name = 'PARAM2'
  36:                                         value = l_text ).
  37:  
  38:   me->show_buttons( ).
  39:  
  40: ENDMETHOD.

Okay that gets a real good start on the Component Controller.  In truth there are quite a few more methods on this object that we’ll get into a little later.  These methods are called by user-events, but were placed at the Component Controller level, because it already had access to the shared Context nodes we created above.






overview

2011-06-02

WD Screen Variants – Assistance Class

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.

Start a new ABAP class ZCL_WDR_SELOPT_VARIANT.  It should inherit from CL_WD_COMPONENT_ASSISTANCE in order to be a true Web Dynpro assistance class (however, this isn’t a requirement).  An Assistance Class is assigned to a Web Dynpro component for two reasons: text elements and class-based coding.

SNAGHTML1e5aeada

Text Elements

I use this class to hold a list of language-dependent label captions that can be translated as needed.

SNAGHTML1e60972f

Classic ABAP Class-based Code

I’ve made the assistance class very important to this project by placing the list of assigned select options in this class.  It also stores a list of dynamic-date functions from RS_VARI_V_INIT.
SNAGHTML1e64b29b

You’ll see later where these methods are called.  The GET_TEXT method is simply a call to Web Dynpro assistance class GET_TEXT.  This makes for a more simple method call inside my Web Dynpro component.  The INIT_VARIVAR_TABLE is called at initialization to populate the MT_VARIVAR variant variables function list.

SNAGHTML1e66f4c9

This method gets a list of the various dynamic date possibilities:

   1: METHOD init_varivar_table.
   2:  
   3:   CALL FUNCTION 'RS_VARI_V_INIT'
   4:     TABLES
   5:       p_varivar = me->mt_varivar[].
   6:  
   7: **********************************************************************
   8: * Hide these dynamic date possibilities.
   9: * We don't have factory calendars configured in D15.
  10: **********************************************************************
  11:  
  12:   DATA: ls_varivar                    TYPE rsvarivar.
  13:   LOOP AT me->mt_varivar[] INTO ls_varivar.
  14:     CASE ls_varivar-runt_fb.
  15:       WHEN 'RS_VARI_V_TODAY_XWD' OR
  16:            'RS_VARI_V_WDAYS_UP_TO_NOW' OR
  17:            'RS_VARI_V_XWD_ACTUAL_MONTH'.
  18:  
  19:         DELETE TABLE me->mt_varivar[] FROM ls_varivar.
  20:  
  21:       WHEN OTHERS.
  22:     ENDCASE.
  23:   ENDLOOP.
  24:  
  25: ENDMETHOD.

Next, let’s dive into the Web Dynpro component itself.







overview

<< previous | next >>