Skip to Content

We all know that when Craig’s not happy, nobody’s happy.

So to keep him happy, this post is divided into two parts.

For those who are only interested in understanding how the SAP component WDR_TEST_UI_ELEMENTS builds a sample RoadMap dynamically, Part 1 of this post will begin to answer these two questions:

1.1) how does the SAP component WDR_TEST_UI_ELEMENTS know when it’s supposed to display a sample RoadMap?

1.2) how does it know exactly what to do to build a sample RoadMap dynamically?

(By “<b>begin to answer”</b>, I mean that <b>Part 1</b> of this post will outline the metadata, flow-of-control, and control variables that are critical to the way in which <b>WDR_TEST_UI_ELEMENTS</b> dynamically builds a <b>sample RoadMap</b>.  Subsequent posts will explain in detail how <b>WDR_TEST_UI_ELEMENTS</b> decides the specific look and feel of the <b>sample RoadMap</b> it builds.)

For those who are also interested in seeing how to achieve the objective I stated in the introduction to this tutorial Exposing Critical SAP Code Paths as WebDynpro(ABAP) RoadMaps: One Case Where Dynamic UI Element Generation Might Be the Right Way to Go, Part 2 of this post will show how we can use what we learned in Part 1 to make our clone component ZWDR_TEST_UI_ELEMENTS display a RoadMap when an action link in the “Programming Trees” library is selected. This RoadMap will initially be just the sample RoadMap displayed by the original component WDR_TEST_UI_ELEMENTS; subsequent posts in this tutorial will show how we can use SAP’s metadata-driven approach to change this sample RoadMap to make it look and feel like the RoadMaps we actually need.

+(To keep the number of images in this post at a minimum, it would be a good idea if readers would take a moment to run the SAP component WDR_TEST_UI_ELEMENTS, select the “RoadMap” action-link from the “Standard” library, and take a look at the resulting display. If you do this, you’ll see that the critical parts of the display are:

a) the navigation tree on the right;

b) the sample RoadMap shown in the top middle of the display;

c) the Settings and Events trays beneath this sample RoadMap.

And if you keep the structure of this display in mind or print off a snapshot of the screen, it will be easier to understand what’s said below.+)

Part 1: How does the thermos bottle know?

Three SAP-delivered metadata tables and four global variables control everything that happens in the SAP-delivered component WDR_TEST_UI_ELEMENTS.

When the component opens up, these three metadata tables are loaded into global itabs within the init_meta_data method of the proxy class CL_WDR_ALL_IN_ONE_UI_ELEM:

* get all libraries

  select * from wdy_ui_library into table mt_ui_library

          order by primary key.

  • get all view elements – below we will build the final list

  select * from wdy_ui_elem_def into table mt_ui_elem_def_all.

  • get all the attributes of these ui elements – below we will build the final list

  select * from wdy_ui_prop_def into table mt_ui_prop_def.faking out the SAP code  !!!.

In particular, if we want a

RoadMap

to display when we select the

Document Numbers by Cost Center

action link of the

Programming Trees

library in our modified component

ZWDR_TEST_UI_ELEMENTS

, then all we have to do is make the SAP code think that we’ve selected the

RoadMap

link from the

Standard

Library.

And to accomplish this “fake-out”, we only have to make a few changes to our handler class

ZCL_WDR_ALL_IN_ONE_UTIL

and our proxy class

ZCL_WDR_ALL_IN_ONE_UIELEM

.

(2A) Changes to the proxy class ZCL_WDR_ALL_IN_ONE_UIELEM

.

First, in the protected section of our handler class

ZCL_WDR_ALL_IN_ONE_UTIL

, we have to declare the new variables:

data M_CUR_LIBRARY_SAVE type WDY_MD_UI_ELEMENT_LIBRARY .
data M_CUR_UI_ELEMENT_SAVE type WDY_MD_UI_ELEMENT_DEF_NAME .

(These will be used to keep the actual library and action link that were selected, so that we can fake the real SAP variables in order to fool the SAP code into thinking that the RoadMap link was selected from the Standard library.)

Next, we have to initialize these variables in the init_view2 method of our handler class (in the same place as the SAP code initializes the SAP variables):

m_cur_library = ‘LGCLDBS’.
m_cur_ui_element = ‘KDF’.
m_cur_library_save = ‘LGCLDBS’.
m_cur_ui_element_save = ‘KDF’.

(We have to do this to avoid blowing off on an “uninitialized obligatory parameter” error when the component initializes.)

Next, we have to recode the on_display_detail method of our handler class ZCL_WDR_ALL_IN_ONE_UTIL so that it fakes out the SAP code into thinking that the customer wants to display a RoadMap:

method ON_DISPLAY_DETAIL.

m_cur_ui_element = i_event->get_string( ‘CUR_UI_ELEMENT’ ).
m_cur_library = i_event->get_string( ‘CUR_LIBRARY’ ).
IF m_cur_library = ‘PRGTRS’.

m_cur_ui_element_save = m_cur_ui_element.
m_cur_library_save = m_cur_library.

m_cur_library = ‘STANDARD’.
m_cur_ui_element = ‘ROAD_MAP’.

ELSE.

m_cur_ui_element_save = m_cur_ui_element.
m_cur_library_save = m_cur_library.

ENDIF.

switch_ui_element2( ).

endmethod.

Finally, in the switch_ui_element2 method of the handler class ZCL_WDR_ALL_IN_ONE_UTIL, we have to be sure to include our new “save” variables when we call the create method of the proxy class ZCL_ALL_IN_ONE_UIELEM

m_cur_view_element->create(

i_library_name = m_cur_library
i_definition_name = m_cur_ui_element

i_library_name_save = m_cur_library_save
i_definition_name_save = m_cur_ui_element_save

i_parent_container = lr_view_elem_container
i_ui_element_group = lr_ui_element_group
i_ui_element_container = lr_ui_element_container
i_root_node = lr_ui_element_root_node
i_hier_tree_context_node = lr_hier_tree_context_node
i_cur_level = 1 ).

(2B) Changes to the proxy class ZCL_WDR_ALL_IN_ONE_UIELEM.

First, we have to declare the necessary “save” control variables:

data M_LIBRARY_NAME_SAVE type WDY_MD_UI_ELEMENT_LIBRARY .
data M_DEFINITION_NAME_SAVE type WDY_MD_UI_ELEMENT_DEF_NAME .

in the protected section of the proxy class ZCL_WDR_ALL_IN_ONE_UIELEM.

Next, in the public section of our proxy class, we have to add two variables to the definition of the create method (so that we can pass our “save” element and library variables as well as the SAP element and library variables):

methods CREATE
importing

value(I_LIBRARY_NAME) type WDY_MD_UI_ELEMENT_LIBRARY
value(I_DEFINITION_NAME) type WDY_MD_UI_ELEMENT_DEF_NAME

value(I_LIBRARY_NAME_SAVE) type WDY_MD_UI_ELEMENT_LIBRARY
value(I_DEFINITION_NAME_SAVE) type WDY_MD_UI_ELEMENT_DEF_NAME

Next, we have to be sure to add our new “save” variables in two methods of our proxy class ZCL_ALL_IN_ONE_UIELEM from which we call the create method of this class. The first of these two methods is the create_aggregatee method:

method CREATE_AGGREGATEE

. . .

  • create a new helper class for displaying the attributes, aggregations and events

  new_level = m_cur_level + 1.

  create object lr_new_view_elem_helper.

  lr_new_view_elem_helper->create(

    i_library_name              = i_aggregatee-library_name

    i_definition_name           = i_aggregatee-definition_name

    i_library_name_save         = m_library_name_save

    i_definition_name_save      = m_definition_name_save

    i_parent_container          = m_parent_container “i_parent_container

    i_ui_element_group          = m_ui_element_group

    i_ui_element_container      = m_ui_element_container

    i_root_node                 = m_root_node

    i_parent_view_element       = m_view_element

    i_parent_aggregation_name   = i_ui_aggr_def-aggregation_name

    i_view_element              = c_new_view_element

    i_hier_tree_context_node    = lr_hier_tree_context_node

    i_hier_tree_context_element = lr_hier_tree_context_element

    i_cur_level                 = new_level ).

  insert lr_new_view_elem_helper into table mt_aggregated_view_elements.

. . .

and the second is the CREATE_CONTAINER_DEFAULT_AGGR method:

method CREATE_CONTAINER_DEFAULT_AGGR

. . .

  • create a new helper class for displaying the attributes, aggregations and events

    new_level = m_cur_level + 1.

    create object lr_new_view_elem_helper.

    lr_new_view_elem_helper->create(

      i_library_name              = ‘STANDARD’

      i_definition_name           = ‘TEXT_VIEW’

      i_library_name_save         = m_library_name_save

      i_definition_name_save      = m_definition_name_save     

      i_parent_container          = m_parent_container “i_parent_container

      i_ui_element_group          = m_ui_element_group

      i_ui_element_container      = m_ui_element_container

      i_root_node                 = m_root_node

      i_parent_view_element       = m_view_element

      i_parent_aggregation_name   = i_ui_aggr_def-aggregation_name

      i_view_element              = lr_text_view

      i_hier_tree_context_node    = lr_hier_tree_context_node

      i_hier_tree_context_element = lr_hier_tree_context_element

      i_cur_level                 = new_level ).

    insert lr_new_view_elem_helper into table mt_aggregated_view_elements.

  enddo.

endmethod.

Finally, we have to recode the on_select_view_element method of our proxy class ZCL_WDR_ALL_IN_ONE_UIELEM so that it acts AS IF the RoadMap action link of the STANDARD library has been selected when in fact, some action link within the Programming Trees library has been selected (e.g. the Document Numbers by Cost Center action link.)

method ON_SELECT_VIEW_ELEMENT.

data:
lr_view_elem_helper like line of mt_aggregated_view_elements,
lr_container type ref to cl_wd_uielement_container,
lt_children type CL_WD_uielement=>tt_uielement,
lr_child like line of lt_children,
id type string,
text type string,

v_ldbnode(30) type c,

idf type string,
idw type string,
idu type string,
idx type string,

v_cnt type i.

CASE m_library_name_save.

WHEN ‘LGCLDBS’.

i_hier_tree_selected_element->

get_attribute( EXPORTING name = ‘TEXT’ IMPORTING value = v_ldbnode ).

  •     save the selected context element of the hierarchy tree

      m_hier_tree_selected_element = i_hier_tree_selected_element.

  •     remove any previous trays

      lt_children = m_parent_container->get_children( ).

      loop at lt_children into lr_child.

        if   lr_child->id cs mc_where_id

          or lr_child->id cs mc_ftchd_id

          or lr_child->id cs mc_used_id

          or lr_child->id cs mc_index_id

          or lr_child->id cs mc_settings_id

          or lr_child->id cs mc_events_id.

          m_parent_container->remove_child( id = lr_child->id ).

        endif.

      endloop.

      clear m_where_tray.

      clear m_fetched_tray.

      clear m_used_tray.

      clear m_index_tray.

      clear m_settings_tray.

      clear m_events_tray.

      concatenate m_prefix mc_where_id into idw.

      concatenate m_prefix mc_ftchd_id into idf.

      concatenate m_prefix mc_used_id  into idu.

      concatenate m_prefix mc_index_id into idx.

      SELECT count( * )

        FROM zwdy_ui_elem_def

        INTO v_cnt

       WHERE display_name = v_ldbnode.

      IF v_cnt = 0.

        concatenate text-017 ` ` v_ldbnode into text.

      ELSE.

        text = text-018.

      ENDIF.

      m_where_tray = add_tray_to_container(

                     i_id               = idw

                     i_parent_container = m_parent_container

                     i_header_text      = text ).

      IF v_cnt = 0.

        concatenate text-019 ` ` v_ldbnode into text.

        m_fetched_tray = add_tray_to_container(

                         i_id               = idf

                         i_parent_container = m_parent_container

                         i_header_text      = text ).

        text = text-020.

        m_used_tray = add_tray_to_container(

                        i_id               = idu

                        i_parent_container = m_parent_container

                        i_header_text      = text ).

        concatenate text-021 ` ` v_ldbnode into text.

        m_index_tray = add_tray_to_container(

                        i_id               = idx

                        i_parent_container = m_parent_container

                        i_header_text      = text ).

        fill_lgcldbs_trays( ).

      ENDIF.

    WHEN ‘PRGTRS’.

  •     in case we are the one to be displayed, do it

      if m_hier_tree_context_element = i_hier_tree_selected_element.

  •       remove the old trays

        lt_children = m_parent_container->get_children( ).

        loop at lt_children into lr_child.

         if   lr_child->id cs mc_where_id

           or lr_child->id cs mc_ftchd_id

           or lr_child->id cs mc_used_id

           or lr_child->id cs mc_index_id

           or lr_child->id cs mc_settings_id

           or lr_child->id cs mc_events_id.

           m_parent_container->remove_child( id = lr_child->id ).

         endif.

        endloop.

        clear m_settings_tray.

        clear m_events_tray.

        clear m_where_tray.

        clear m_fetched_tray.

        clear m_used_tray.

        clear m_index_tray.

  •       create new ones

        create_settings_tray( ).

        create_events_tray( ).

      else.

  •       otherwise propagate it down the chain

        loop at mt_aggregated_view_elements into lr_view_elem_helper.

          lr_view_elem_helper->on_select_view_element( i_hier_tree_selected_element ).

        endloop.

      endif.

    WHEN OTHERS.

  ENDCASE.

endmethod.

Note that when an action link has been selected from the Logical Database library, the component will just display the four trays we built in the preceeding tutorial. But when an action link has been selected fom the Programming Trees library, the component will behave AS IF the RoadMap link has been selected from the Standard library.

Summary of What We’ve Learned and Done So Far

All we’ve done so far is: ℹ learn how the original SAP component

WDR_TEST_UI_ELEMENTS

knows when to invoke the

NEW_ROAD_MAP

method of

CL_WD_ROAD_MAP

; (ii) learn how to fake this process in our modified component

ZWDR_TEST_UI_ELEMENTS

.

We still have to learn:

(iii) how the original SAP component “fills-in” the new RoadMap it’s created with RoadMapSteps, actions, and events;

(iv) how to emulate this “fill-in” process in our modified component so that it creates exactly the RoadMaps we want (depending on what node of the right-hand navigation tree has been selected.)

As mentioned above, tasks (iii) and (iv) are not trivial – there is a whole lot of information that we still have to learn about the

create_settings

,

create_events

, and

create_aggregations

method of the original SAP proxy class

CL_WDR_ALL_IN_ONE_UIELEM

.

But we’ve made a good start, and the rest is just plowing thru the SAP code and understanding how the metadata in the two tables

wdy_ui_elem_def

and

wdy_ui_prop_def

are used by the original SAP component to “fill-in” a new

RoadMap

that it’s created.

To report this post you need to login first.

Be the first to leave a comment

You must be Logged on to comment or reply to a post.

Leave a Reply