An Archaeological “Dig” into SAP Metadata (Part 9 of “Event-Driven” Tutorial on WD-ABAP Component WDR_TEST_UI_ELEMENTS)
Upon reviewing the eight parts of this tutorial so far:
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.
I am still amazed at how little had to be actually revised (or coded from scratch) in order to change the original component WDR_TEST_UI_ELEMENTS into a new component ZWDR_TEST_UI_ELEMENTS that does exactly what we wanted.
In particular, the new component now opens with the tray view “A” , the tree view “B”, and the detail view “C” respectively displayed on the lefthand-side, righthand-side, and middle of the frame:
A: Opening Tray View (lefthand side)
B: Opening Tree View (righthand side)
C: Opening Detail View (middle)
And when any lower-level node is selected from the tree at the right (e.g. “LFA1”), the new component correctly expands the middle detail view into three trays:
D: Expanded Detail View (middle) after lower-level node selection from righthand tree
With the three trays now displaying in the middle detail view, the next task is to fill these trays with the information that should be in them. And in order to accomplish this task, three things have to be done:
like line of lt_fixed_values.
-
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.
-
create the settings tray itself
concatenate m_prefix mc_settings_id into id.
concatenate text-005 ` ` -display_name into text.
m_settings_tray = add_tray_to_container(
i_id = id
i_parent_container = m_parent_container
i_header_text = text ).
-
in case the view element can be p13ned, offer a toolbar button
-
this is only possible in case it is a ui element
-
read table mt_ui_elem_def
-
with key library_name = m_library_name
-
definition_name = m_definition_name
-
transporting no fields.
-
if sy-subrc = 0.
-
lr_toolbar = cl_wd_toolbar=>new_toolbar( ).
-
m_settings_tray->set_toolbar( lr_toolbar ).
-
text = text-016.
-
lr_toolbar_button = cl_wd_toolbar_button=>new_toolbar_button( text = text on_action = ‘OPEN_PERS’ ).
-
lr_toolbar->add_toolbar_item( lr_toolbar_button ).
-
endif.
-
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 ).
*
-
change the text of the header of the parent group in case we are not being aggregated
-
if m_parent_view_element is not bound.
-
lr_ui_element_group_header ?= m_ui_element_group->get_header( ).
-
display_name_txt = <ui_elem_def>-display_name.
-
lr_ui_element_group_header->set_text( display_name_txt ).
-
endif.
-
handle the properties of this view element
index = 1.
loop at mt_ui_prop_def assigning
where library_name = m_library_name
and definition_name = m_definition_name.
-
save the index of the current property – needed later
condense index no-gaps.
-
assign the value set, in case it’s not a boolean attribute
clear lt_value_set[].
if ‘WDY_BOOLEAN’.
-
if <ui_prop_def>-type <> ‘WDY_MD_TRANSLATABLE_TEXT’.
-
is_dtel = abap_true.
-
try.
-
rtti_attr ?= cl_abap_typedescr=>describe_by_name( <ui_prop_def>-type ).
-
catch cx_root. “#EC *
-
is_dtel = abap_false.
-
endtry.
-
if is_dtel = abap_true.
-
get the fixed values
-
call method rtti_attr->get_ddic_fixed_values
-
receiving
-
p_fixed_values = lt_fixed_values
-
exceptions
-
no_ddic_type = 1
-
others = 2.
-
if sy-subrc = 2.
-
message x000(00).
-
elseif sy-subrc = 0.
-
create a new value set
-
loop at lt_fixed_values assigning <fixed_value>.
-
value_set_item-key = <fixed_value>-low.
-
value_set_item-value = <fixed_value>-ddtext.
-
insert value_set_item into table lt_value_set.
-
endloop.
-
endif.
-
endif.
-
endif.
-
replace the value set that exists at the attribute
-
this means replacement by a new one or clear of an old one
attribute_name = -property_name.
-
m_settings_node_info->set_attribute_value_set(
-
name = attribute_name
-
value_set = lt_value_set ).
endif.
-
create the path to the attribute
-
special handling for multiNodeAttribute ones
if -binding_type = ’02’.
-
create an attribute at the data node and fill all elements with a default value there
-
attribute_info-node_info = m_data_node_info.
-
attribute_info-name = <ui_prop_def>-property_name.
-
attribute_info-is_read_only = abap_false.
-
attribute_info-type_name = <ui_prop_def>-type.
-
m_data_node_info->add_attribute( attribute_info ).
-
lt_context_elements = m_data_node->get_elements( ).
name = -property_name.
-
loop at lt_context_elements into lr_context_element.
-
attribute_value = get_default_value( <ui_prop_def> ).
-
lr_context_element->set_attribute( name = name value = attribute_value ).
-
endloop.
concatenate m_data_node_path ‘.’ name into attribute_path.
elseif -binding_type = ’03’.
-
it binds to a node – that goes to the data node
attribute_path = m_data_node_path.
else.
-
just a normal attribute
concatenate m_root_node_path ‘.’ m_settings_node_id ‘.’ -property_name into attribute_path.
endif.
-
in case it’s type object, display the binding path
-
if <ui_prop_def>-type = ‘OBJECT’.
-
m_settings_node->set_attribute( name = attribute_name value = attribute_path ).
-
endif.
-
add the ui elements to the settings group that represent the new attributes
-
=> first thing to add is the label
concatenate m_prefix new_label(
id = label_id
label_for = attr_ui_element_id
text = display_name_txt
view = m_view ).
-
=> set the layout of the label
lr_matrix_head_data = cl_wd_matrix_head_data=>new_matrix_head_data( element = lr_label width = ‘1%’ ).
lr_label->set_layout_data( lr_matrix_head_data ).
-
=> next thing to add is the ui element that contains the current value
if strlen( -binding_type = ’02’.
-
it’s of binding type multiNodeAttribute, which always requires a dropdownbyindex
lr_attr_ui_element = cl_wd_dropdown_by_idx=>new_dropdown_by_idx(
bind_texts = attribute_path
id = attr_ui_element_id
view = m_view ).
elseif -binding_type = ’03’.
-
pure node binding will result in a text view containing message explaining the binding type
text = text-013.
lr_attr_ui_element = cl_wd_text_view=>new_text_view(
text = text
id = attr_ui_element_id
view = m_view ).
else.
-
all other cases
case -type.
when ‘WDY_BOOLEAN’.
-
it’s a checkbox
lr_attr_ui_element = cl_wd_checkbox=>new_checkbox(
bind_checked = attribute_path
id = attr_ui_element_id
view = m_view ).
when ‘OBJECT’.
-
it’s a disabled input field that contains the binding path
lr_attr_ui_element = cl_wd_input_field=>new_input_field(
bind_value = attribute_path
id = attr_ui_element_id
enabled = abap_false
view = m_view ).
when ‘STRING’ or ‘WDY_MD_TRANSLATABLE_TEXT’ or ‘I’ or ‘INT4’ or ‘D’ or ‘F’.
-
it’s an enabled input field
lr_attr_ui_element = cl_wd_input_field=>new_input_field(
bind_value = attribute_path
id = attr_ui_element_id
view = m_view ).
when ‘XSTRING’.
lr_attr_ui_element = cl_wd_text_view=>new_text_view(
bind_text = attribute_path
id = attr_ui_element_id
view = m_view ).
when ‘STRING_TABLE’.
lr_attr_ui_element = cl_wd_text_edit=>new_text_edit(
bind_value = attribute_path
id = attr_ui_element_id
view = m_view ).
when others.
-
it’s a dropdown listbox with some fixed values
lr_attr_ui_element = cl_wd_dropdown_by_key=>new_dropdown_by_key(
bind_selected_key = attribute_path
id = attr_ui_element_id
view = m_view ).
endcase.
endif.
-
=> set the layout of the new ui element
lr_matrix_data = cl_wd_matrix_data=>new_matrix_data( element = lr_attr_ui_element width = ‘100%’ ).
lr_attr_ui_element->set_layout_data( lr_matrix_data ).
-
=> add the label and the ui element to the settings group
m_settings_tray->add_child( lr_label ).
m_settings_tray->add_child( lr_attr_ui_element ).
-
bind the current attribute of the ui element to the current context attribute
-
if <ui_prop_def>-is_bindable <> ’00’. “and <ui_prop_def>-type <> ‘OBJECT’.
-
in case we need to create the view element, we just collect the parameters
-
if m_view_element is not bound.
-
add the additional parameters to the parameter tab for the new_ method call
-
concatenate ‘BIND_’ <ui_prop_def>-property_name into method_param-name.
-
method_param-kind = cl_abap_objectdescr=>exporting.
-
create data lr_dummy_string.
-
lr_dummy_string->* = attribute_path.
-
method_param-value = lr_dummy_string.
-
insert method_param into table lt_method_params.
-
else.
-
we directly perform a BIND_ method call
-
concatenate ‘BIND_’ <ui_prop_def>-property_name into method_name.
-
call method m_view_element->(method_name)
-
exporting
-
path = attribute_path.
-
endif.
-
endif.
-
increase the index counter by one
add 1 to index.
endloop.
-
create the view element in case it has not already been created from outside
-
if m_view_element is not bound.
-
add the additional parameters to the parameter tab for the new_ method call
-
method_param-name = ‘ID’.
-
method_param-kind = cl_abap_objectdescr=>exporting.
-
create data lr_dummy_string.
-
lr_dummy_string->* = mc_final_ui_element_id.
-
method_param-value = lr_dummy_string.
-
insert method_param into table lt_method_params.
*
-
method_param-name = ‘VIEW’.
-
method_param-kind = cl_abap_objectdescr=>exporting.
-
get reference of m_view into method_param-value.
-
insert method_param into table lt_method_params.
*
-
method_param-name = ‘CONTROL’.
-
method_param-kind = cl_abap_objectdescr=>receiving.
-
get reference of m_view_element into method_param-value.
-
insert method_param into table lt_method_params.
*
-
create an instance of the new view element
-
concatenate ‘NEW_’ <ui_elem_def>-runtime_class+6 into method_name.
-
call method (<ui_elem_def>-runtime_class)=>(method_name)
-
parameter-table
-
lt_method_params.
*
-
add it to the hierarchy tree
-
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_false ).
-
m_hier_tree_context_element->set_attribute( name = ‘HAS_CHILDREN’ value = abap_false ).
-
m_hier_tree_context_element->set_attribute( name = ‘TEXT’ value = <ui_elem_def>-display_name ).
-
endif.
*
-
place it inside of the ui element tray in case we are at the top level
-
if m_parent_view_element is not bound.
-
since it resides inside of the group with a matrix layout, create the
-
appropriate layout data for it
-
lr_ui_element ?= m_view_element.
*
-
in case the ui element supports a label, create the label with some fixed values
-
if <ui_elem_def>-label_support = ’01’ or
-
<ui_elem_def>-label_support = ’02’.
-
create the label
-
text = text-014.
-
lr_label = cl_wd_label=>new_label(
-
id = mc_final_ui_element_label_id
-
text = text
-
label_for = lr_ui_element->id ).
-
lr_matrix_head_data = cl_wd_matrix_head_data=>new_matrix_head_data(
-
element = lr_label
-
v_align = if_wdl_standard=>cellvalign_top
-
width = ” ).
-
lr_label->set_layout_data( lr_matrix_head_data ).
-
m_ui_element_container->add_child( index = 1 the_child = lr_label ).
*
-
create the matrix data for the ui element
-
lr_matrix_data = cl_wd_matrix_data=>new_matrix_data(
-
element = lr_ui_element
-
v_align = if_wdl_standard=>cellvalign_top
-
width = ‘100%’ ).
-
lr_ui_element->set_layout_data( lr_matrix_data ).
-
m_ui_element_container->add_child( index = 2 the_child = lr_ui_element ).
-
else.
-
create the matrix head layout data for the ui element
-
lr_matrix_head_data = cl_wd_matrix_head_data=>new_matrix_head_data(
-
element = lr_ui_element
-
v_align = if_wdl_standard=>cellvalign_top
-
width = ‘100%’ ).
-
lr_ui_element->set_layout_data( lr_matrix_head_data ).
-
m_ui_element_container->add_child( index = 1 the_child = lr_ui_element ).
-
endif.
-
endif.
endmethod.