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...
Sieving Presentation from Business Logic When the Business Application Area is Software Development ...
Apache Struts/M2 and SAP WebDynpro/MVC: Can these paradigms alone guarantee separation of business a...
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 ...
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-A...
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:
😧 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.