Learning what you don’t need is as important as learning what you do (Parts 10b-c) of “Event-Driven” Tutorial on WDR_TEST_UI_ELEMENTS)
At the end of Part 10a of this tutorial:
As James Carville said to Bill Clinton in 1992: “It’s the indices, stupid” (Part 10a of “Event-Driven” Tutorial on WDR_TEST_UI_ELEMENTS)
An Archaeological “Dig” into SAP Metadata (Part 9 of “Event-Driven” Tutorial on WD-ABAP Component WDR_TEST_UI_ELEMENTS)
When Presentation and Business Logic are Jumbled, Even Minor Housekeeping is Trickier Than It Should Be (Part 8 of Event-Driven Tutorial on WDR_TEST_UI_ELEMENTS)
Sieving Presentation from Business Logic When the Business Application Area is Software Development (Part 7 of “Event-Driven” Tutorial on SAP-Delivered WDABAP Component WDR_TEST_UI_ELEMENTS)
Apache Struts/M2 and SAP WebDynpro/MVC: Can these paradigms alone guarantee separation of business and presentation logic? (Part 6b of Tutorial on WDR_TEST_UI_ELEMENTS)
Part 6a of Event-Driven Tutorial on WDABAP Component WDR_TEST_UI_ELEMENTS
If you’ve written something in SAP from scratch, you (probably) haven’t bothered to understand what someone else has already done (Part 5 of “Event-Driven” Tutorial on WD-ABAP Component WDR_TEST_UI_ELEMENTS)
Part 4 of “Event-Driven” Tutorial on the WD-ABAP Component WDR_TEST_UI_ELEMENTS.
“Procedural” Recap of What’s Been Learned So Far in “Experiential” (“Event-Driven”) Tutorial on WD-ABAP component WDR_TEST_UI_ELEMENTS
The class infrastructure of WDR_UI_TEST_ELEMENTS is exquisite for lazy cloning and change-ups.
Experiential vs Procedural Tutorials: “Breaking” WDR_TEST_UI_ELEMENTS to Learn From It.
we had created the custom metadata table that we need to use in order to load the four trays of detail information we want to display when some node of a Logical Database is selected from the right hand tree view:
So we’re now ready to use these metadata to expand the four trays above like this:
And therefore, we start on this task by looking to see how the original SAP component WDR_TEST_UI_ELEMENTS expands the “Settings” tray it displays in the middle tray view – in paticular, how it does this using the
create_settings_tray
method of the proxy class
CL_WDR_ALL_IN_ONE_UIELEM.
Well, to make a long story short, it turns out that we can
try
to modify
create_settings_tray
to make it do what we want, but if we try this, we’re going to have to go very very deep into the SAP-delivered code and clone a whole bunch of infrastructure classes in order to be able to modify the one we really need to modify – the SAP-delivered class
/1WDA/LSTANDARD
.
Furthermore, as we’re considering this very unattractive option, it occurs to us that we’ve already added action-links to trays before – in the
init_view2
method of the class
ZCL_WDR_ALL_IN_ONE_UTIL
that we cloned from the SAP-delivered class
CL_WDR_ALL_IN_ONE_UTIL
. And in this method, we didn’t have to do anything near as complicated as the stuff that SAP is doing in
create_settings_tray
.
Equally importantly, it occurs to us that if we don’t need all the stuff in
create_settings_tray
, then maybe we don’t need all of the stuff in
create_settings
either – maybe this is all just stuff particular to the business logic which the original component has to use to display settings and events of UI elements. So, before we start the main task of adding links to trays using the code that SAP has in
init_view2
, we decide to take a closer look at
create_settings
to see what we really need from this component.
To make a long-story short again, it turns out that all we need from the
create_settings
component is the code that creates the very topmost node of the tree displayed the righthand treeview shown above. And since we can move this code to our new method
create_lgcldb_tree
, it turns out that we can do some simplifying housekeeping as follows.
Step 1
: Clean-up our modified
create
method.
In If you’ve written something in SAP from scratch, you (probably) haven’t bothered to understand what someone else has already done (Part 5 of “Event-Driven” Tutorial on WD-ABAP Component WDR_TEST_UI_ELEMENTS) of this tutorial, we modified the
create
method of
ZCL_WDR_ALL_IN_ONE_UIELEM
so that it invoked the method we had written to build the right-hand side tree view. These modications are shown below in bolded italics:
method create.
data:
cur_id_variation type string.
-
get a new id variation component
m_last_used_id_variation = m_last_used_id_variation + 1.
m_cur_id_variation = m_last_used_id_variation.
-
save some stuff
m_library_name = i_library_name.
m_definition_name = i_definition_name.
m_parent_container = i_parent_container.
m_ui_element_group = i_ui_element_group.
m_ui_element_container = i_ui_element_container.
m_root_node = i_root_node.
m_root_node_info = i_root_node->get_node_info( ).
m_root_node_path = i_root_node->get_meta_path( withoutcontroller = abap_true ).
m_view = i_ui_element_group->view.
m_parent_view_element = i_parent_view_element.
m_parent_aggregation_name = i_parent_aggregation_name.
m_view_element = i_view_element.
m_hier_tree_context_node = i_hier_tree_context_node.
m_hier_tree_context_element = i_hier_tree_context_element.
m_cur_level = i_cur_level.
-
create prefix for all generated nodes, view elements, etc.
cur_id_variation = m_cur_id_variation.
condense cur_id_variation.
concatenate ‘C’ cur_id_variation ‘_’ into m_prefix.
-
create the different areas
create_settings( ).
create_events( ).
+* create_aggregations( ).
CASE m_library_name.
WHEN ‘LGCLDBS’.
create_lgcldb_tree( ).
WHEN OTHERS.
create_aggregations( ).
ENDCASE.+
if m_hier_tree_context_element is bound and m_hier_tree_context_element = m_hier_tree_selected_element.
-
create the two trays, if necessary
create_settings_tray( ).
create_events_tray( ).
endif.
endmethod.
But as will be seen in a moment, it turns out that we only need one small snippet of code from
create_settings
and no code at all from
create_events
. Plus, since we’ve removed the original UI Element libraries from the list of libraries our cloned component can display in its initial left-hand side tray-view, we don’t need anything from
create_aggregations
either. And therefore, we can simplify our
create
method to:
method CREATE.
data:
cur_id_variation type string.
-
get a new id variation component
m_last_used_id_variation = m_last_used_id_variation + 1.
m_cur_id_variation = m_last_used_id_variation.
-
save some stuff
m_library_name = i_library_name.
m_definition_name = i_definition_name.
m_parent_container = i_parent_container.
m_ui_element_group = i_ui_element_group.
m_ui_element_container = i_ui_element_container.
m_root_node = i_root_node.
m_root_node_info = i_root_node->get_node_info( ).
m_root_node_path = i_root_node->get_meta_path( withoutcontroller = abap_true ).
m_view = i_ui_element_group->view.
m_parent_view_element = i_parent_view_element.
m_parent_aggregation_name = i_parent_aggregation_name.
m_view_element = i_view_element.
m_hier_tree_context_node = i_hier_tree_context_node.
m_hier_tree_context_element = i_hier_tree_context_element.
m_cur_level = i_cur_level.
-
create prefix for all generated nodes, view elements, etc.
cur_id_variation = m_cur_id_variation.
condense cur_id_variation.
concatenate ‘C’ cur_id_variation ‘_’ into m_prefix.
-
create the different areas
CASE m_library_name.
WHEN ‘LGCLDBS’.
create_lgcldb_tree( ).
-
later, we’ll add methods to build trees for the
-
action links in our other two kinds of metadata
-
libraries (“Programming Trees” and “Report Sets”)
WHEN OTHERS.
ENDCASE.
endmethod.
Step 2
: Take what we need from
create_settings
and put it in
create_lgcldb_trees
As noted above, all we need from
create_settings
is the little snippet of code which creates the topmost root node of the tree to be displayed in the right-hand side tree view (e.g. the node “Vendor Database” in the illustration above.) So we take this code and place it in our
create_lgcldb_tree
method as follows (see boldfaced and italicized code):
method CREATE_LGCLDB_TREE.
data:
id type string,
label_for_id type string,
lr_tray type ref to cl_wd_tray,
text type string,
lr_new_view_elem_helper type ref to zcl_wdr_all_in_one_uielem, ” Part 5 try 2 20060908
lr_new_view_element type ref to cl_wdr_view_element,
class_name type string,
method_name type string,
lt_method_params type abap_parmbind_tab,
method_param like line of lt_method_params,
lt_aggregatees type wdy_ui_elem_def_table,
lt_zldbn type tt_zldbn, ” Part 5 try 2 20060908
v_hasch type abap_bool, ” Part 5 try 2 20060908
lr_label type ref to cl_wd_label,
lr_text_view type ref to cl_wd_text_view,
lr_matrix_head_data type ref to cl_wd_matrix_head_data,
lr_matrix_data type ref to cl_wd_matrix_data,
lr_aggregation_node_info type ref to if_wd_context_node_info,
lr_aggregation_node type ref to if_wd_context_node,
lr_context_element type ref to if_wd_context_element,
path type string,
texts_path type string,
node_name type string,
lr_dropdown type ref to cl_wd_dropdown_by_idx,
index type i,
aggregation_allowed type abap_bool,
lr_container type ref to cl_wd_uielement_container,
lr_child type ref to cl_wd_uielement,
lr_rtti type ref to cl_abap_datadescr,
lr_data type ref to data,
is_container type abap_bool,
lr_object type ref to object,
repeat type i,
+
-
begin add-in of code 9/25/2006
lr_ui_element_group_header type ref to cl_wd_caption,
display_name_txt type string.
-
end add-in of code 9/25/2006
+ like line of mt_zldbn. ” Part 5 try 2 20060908
-
” Part 5 try 2 20060908 (declarations from create_aggregatee. except what’s been declared above)
data:
initial_path type string,
lr_hier_tree_context_node type ref to if_wd_context_node,
lr_hier_tree_context_element type ref to if_wd_context_element,
lr_save_tree_context_element type ref to if_wd_context_element, ” Part 5 try 2 20060908
icon type string.
-
“
-
get the data of the current view element
read table mt_ui_elem_def_all
with key library_name = m_library_name
definition_name = m_definition_name
assigning 0.
-
big problem…
message x000(00).
endif.
+
-
begin add-in of code 9/25/2006
-
create a context node where all the settings of the current UI element are stored
concatenate m_prefix mc_settings_id into m_settings_node_id.
m_settings_node_info = create_settings_node(
i_node_name = m_settings_node_id
i_parent_node_info = m_root_node_info
i_is_mandatory = abap_true ).
m_settings_node = m_root_node->get_child_node( m_settings_node_id ).
-
create a data node where all multi node settings are stored, like for all view elements
-
that have a data source or attributes with type multiNodeAttribute
concatenate m_prefix mc_data_id into m_data_node_id.
m_data_node_info = create_data_node( i_parent_node_info = m_root_node_info ).
m_data_node_path = m_data_node->get_meta_path( withoutcontroller = abap_true ).
-
end add-in of code 9/25/2006
m_hier_tree_context_element = m_hier_tree_context_node->create_element( ).
m_hier_tree_context_node->bind_element( new_item = m_hier_tree_context_element set_initial_elements = abap_false ).
m_hier_tree_context_element->set_attribute( name = ‘EXPANDED’ value = abap_true ).
m_hier_tree_context_element->set_attribute( name = ‘HAS_CHILDREN’ value = abap_true ).
m_hier_tree_context_element->set_attribute( name = ‘TEXT’ value = .
**************************************************
-
this is from original create_aggregations
concatenate m_prefix mc_aggr_explaination_id bind_element( new_item = lr_context_element set_initial_elements = abap_false ).
**************************************************
**************************************************
-
this is from original create_aggregatee
lr_hier_tree_context_node = m_hier_tree_context_element->get_child_node( ‘UI_ELEMENT_HIER_REC’ ).
lr_hier_tree_context_element = lr_hier_tree_context_node->create_element( ).
lr_hier_tree_context_node->bind_element( new_item = lr_hier_tree_context_element set_initial_elements = abap_false ).
IF set_attribute( name = ‘ICON’ value = icon ).
*************************************************
**************************************************
-
this is from original create_aggregations
-
set the lead selection of the aggregation node to the currently aggregated view element
index = sy-tabix.
lr_aggregation_node->set_lead_selection_index( index ).
**************************************************
lr_hier_tree_context_element->get_attribute( EXPORTING name = ‘HAS_CHILDREN’ IMPORTING value = v_hasch ).
IF v_hasch = abap_true.
lr_save_tree_context_element = m_hier_tree_context_element.
m_hier_tree_context_element = lr_hier_tree_context_element.
create_lgcldb_nodes( ).
m_hier_tree_context_element = lr_save_tree_context_element.
ENDIF.
endloop.
And once having done these two bits of clean-up, we can now return to the task of expanding our middle trays without needing any code from
create_settings
,
create_settings_node
, or
create_settings_tray
.
In particular, to expand our middle level trays as shown above, we modify the method
on_select_view_element
of
ZCL_WDR_ALL_IN_ONE_UIELEM
so that it invokes a new method
fill_lgcldbs_trays
and then steal the SAP code from the
init_view2
method of
CL_WDR_ALL_IN_ONE_UTIL
to put in this new method.
The modified
on_select_view_element
method winds up looking just like it did at the end of An Archaeological “Dig” into SAP Metadata (Part 9 of “Event-Driven” Tutorial on WD-ABAP Component WDR_TEST_UI_ELEMENTS), except that it now invokes the new
fill_lgcldbs_trays
method (see boldfaced and italicized code below):
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.
i_hier_tree_selected_element->get_attribute( EXPORTING name = ‘TEXT’ IMPORTING value = v_ldbnode ).
-
remove the old trays
lt_children = m_parent_container->get_children( ).
loop at lt_children into lr_child.
-
if lr_child->id cs mc_settings_id or lr_child->id cs mc_events_id.
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.
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.
-
save the selected context element of the hierarchy tree
m_hier_tree_selected_element = i_hier_tree_selected_element.
CASE m_library_name.
WHEN ‘LGCLDBS’.
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 ).
get_attribute( EXPORTING name = ‘TEXT’ IMPORTING value = v_ldbnode ).
-
fill the where tray
CLEAR mt_zldbm.
SELECT *
FROM zldbm
INTO
TABLE mt_zldbm
WHERE ldbname = m_definition_name
AND nodename = v_ldbnode
AND ( infotype = ‘WE’ OR infotype = ‘WV’ )
ORDER
BY infotype colname.
IF sy-subrc = 0.
LOOP AT mt_zldbm ASSIGNING -colname ‘:’ coltext INTO display_txt.
-
create a linktoaction for the current view element inside of the current tray
lr_link_to_action = cl_wd_link_to_action=>new_link_to_action(
id = id_txt
on_action = ‘DISPLAY_COL_DETAIL’
text = display_txt
view = m_view ).
-
create the grid layout data for the link to action
lr_matrix_head_data = cl_wd_matrix_head_data=>new_matrix_head_data( lr_link_to_action ).
-
assign the layout data to the link to action
lr_link_to_action->set_layout_data( lr_matrix_head_data ).
-
add the link to action to the current tray
m_where_tray->add_child( lr_link_to_action ).
ENDLOOP.
ENDIF.
-
fill the select tray
CLEAR mt_zldbm.
SELECT *
FROM zldbm
INTO
TABLE mt_zldbm
WHERE ldbname = m_definition_name
AND nodename = v_ldbnode
AND ( infotype = ‘SE’ or infotype = ‘SV’ )
ORDER
BY infotype colname.
IF sy-subrc = 0.
LOOP AT mt_zldbm ASSIGNING -colname ‘:’ coltext INTO display_txt.
-
create a linktoaction for the current view element inside of the current tray
lr_link_to_action = cl_wd_link_to_action=>new_link_to_action(
id = id_txt
on_action = ‘DISPLAY_COL_DETAIL’
text = display_txt
view = m_view ).
-
create the grid layout data for the link to action
lr_matrix_head_data = cl_wd_matrix_head_data=>new_matrix_head_data( lr_link_to_action ).
-
assign the layout data to the link to action
lr_link_to_action->set_layout_data( lr_matrix_head_data ).
-
add the link to action to the current tray
m_fetched_tray->add_child( lr_link_to_action ).
ENDLOOP.
ENDIF.
-
fill the “used-lower-down” tray
CLEAR mt_zldbm.
SELECT *
FROM zldbm
INTO
TABLE mt_zldbm
WHERE ldbname = m_definition_name
AND nodename = v_ldbnode
AND infotype = ‘UE’.
IF sy-subrc = 0.
LOOP AT mt_zldbm ASSIGNING -colname ‘:’ coltext INTO display_txt.
-
create a linktoaction for the current view element inside of the current tray
lr_link_to_action = cl_wd_link_to_action=>new_link_to_action(
id = id_txt
on_action = ‘DISPLAY_COL_DETAIL’
text = display_txt
view = m_view ).
-
create the grid layout data for the link to action
lr_matrix_head_data = cl_wd_matrix_head_data=>new_matrix_head_data( lr_link_to_action ).
-
assign the layout data to the link to action
lr_link_to_action->set_layout_data( lr_matrix_head_data ).
-
add the link to action to the current tray
m_used_tray->add_child( lr_link_to_action ).
ENDLOOP.
ENDIF.
-
fill the “index” tray
CLEAR mt_zldbm.
SELECT *
FROM zldbm
INTO
TABLE mt_zldbm
WHERE ldbname = m_definition_name
AND nodename = v_ldbnode
AND infotype = ‘IX’.
IF sy-subrc = 0.
LOOP AT mt_zldbm ASSIGNING -colname ‘:’ coltext INTO display_txt.
-
create a linktoaction for the current view element inside of the current tray
lr_link_to_action = cl_wd_link_to_action=>new_link_to_action(
id = id_txt
on_action = ‘DISPLAY_COL_DETAIL’
text = display_txt
view = m_view ).
-
create the grid layout data for the link to action
lr_matrix_head_data = cl_wd_matrix_head_data=>new_matrix_head_data( lr_link_to_action ).
-
assign the layout data to the link to action
lr_link_to_action->set_layout_data( lr_matrix_head_data ).
-
add the link to action to the current tray
m_index_tray->add_child( lr_link_to_action ).
ENDLOOP.
ENDIF.
endmethod.
Note for the unwary: I had to modify the custom table zldbm created in Part 9 so that none of the colnames were lower-case. This is because they’re used to create action-link id’s in the above code, and WD-ABAP does not permit lower-case letters in element ids.
At the time Parts10bc was posted, I thought I had all this “needed code” from the original method. But it turned out I had overlooked an obvious piece of code that needed to be incorporated as well, in order to create a new contest node when a new action link is selected from a lefthand side library.
In particular, see the revised main post above for the context-node creation code that was left out.