I have a scenario where I'd like to N instances of a view to the TransparentContainer
on a view with each receiving different parameters. To accomplish this I wrote some logic to dynamically create a cl_wd_view_container_uielement
, add it to the cl_wd_uielement_container
(the TransparentContainer
on the main view) and then fire a plug using dynamic navigation to send my parameters. The code can be found below.
This all works with one problem: the created instances are not unique so I basically add N copies of the same view. N plugs are fired and handled but the last one sets the parameters for all views as there's just one instance. The view's WDDOMODIFYVIEW
is also only fired once.
The code below was repurposed and cleaned up from a working version so I know it's possible. The big difference is that I'm adding a view from the same WDC in my scenario. In the original application the dynamically added view has its own Web Dynpro component and the caller also provides a dynamically created component usage.
Is there some way of creating multiple instances that I'm missing? Should I provide a component usage after all in this case? I've been tinkering with this for a few hours now but am not making any progress so I'd welcome any input to get me on the right track.
Code from the main view:
DATA:
lo_container TYPE REF TO cl_wd_uielement_container,
lo_subview TYPE REF TO cl_wd_view_container_uielement,
lo_flow_data TYPE REF TO cl_wd_flow_data,
lo_view_controller TYPE REF TO if_wd_view_controller,
lo_component_usage TYPE REF TO if_wd_component_usage,
lo_wdr_view TYPE REF TO cl_wdr_view,
lo_component_api TYPE REF TO if_wd_component,
lt_posts TYPE ztt_fi_vernot_posts,
ls_post LIKE LINE OF lt_posts,
lt_parameters TYPE wdr_event_parameter_list,
ls_parameter TYPE wdr_event_parameter,
lv_view_id TYPE string,
lv_source_plug_name TYPE string,
lv_target_embed_pos TYPE string,
lv_param_value TYPE REF TO DATA.
FIELD-SYMBOLS:
<lv_param_value> TYPE bu_partner
.
lt_posts = wd_this->mo_model->get_posts( iv_open = abap_true ).
" Retrieve and refresh the view container.
lo_wdr_view ?= wd_this->wd_get_api( ).
lo_container ?= lo_wdr_view->root_element.
lo_container ?= lo_wdr_view->get_element( 'TC_POSTS' ).
lo_container->remove_all_children( ).
LOOP AT lt_posts INTO ls_post.
" View and plug IDs should be unique.
CONCATENATE 'POSTS_' ls_post-index INTO lv_view_id.
CONCATENATE 'OUTPLUG_' ls_post-index INTO lv_source_plug_name.
" Create a new view.
lo_subview = cl_wd_view_container_uielement=>new_view_container_uielement( id = lv_view_id ).
lo_flow_data = cl_wd_flow_data=>new_flow_data( element = lo_subview ).
lo_subview->set_layout_data( lo_flow_data ).
lo_subview->set_layout_data( cl_wd_flow_data=>new_flow_data( element = lo_subview ) ).
lo_container->add_child( lo_subview ).
lo_view_controller = wd_this->wd_get_api( ).
CONCATENATE 'V_MAIN/' lv_view_id INTO lv_target_embed_pos.
* This was present in the source, returning a component usage via create_comp_usage_of_same_type()
* lo_component_usage = wd_comp_controller->get_component( iv_compcnt = ls_post-index ).
lo_view_controller->prepare_dynamic_navigation(
source_window_name = 'W_MAIN'
" Found in the window structure for this View
source_vusage_name = 'V_MAIN_USAGE_0'
source_plug_name = lv_source_plug_name
" target_component_name = '[WDC name]' " Optional?
" target_component_usage = lo_component_usage->name " Optional?
target_view_name = 'V_POSTS'
target_plug_name = 'SET_PARAMS'
target_embedding_position = lv_target_embed_pos ).
" Fill the paramaters. Note that the values should be passed as pointers.
REFRESH lt_parameters.
CLEAR ls_parameter.
ls_parameter-name = zcl_fi_vernot=>gcs_plugs-params-bp.
CREATE DATA lv_param_value LIKE ls_post-bp.
ASSIGN lv_param_value->* TO <lv_param_value>.
<lv_param_value> = ls_post-bp.
ls_parameter-value = lv_param_value.
INSERT ls_parameter INTO TABLE lt_parameters.
" Do the same for the contract.
CLEAR ls_parameter.
ls_parameter-name = zcl_fi_vernot=>gcs_plugs-params-contract.
CREATE DATA lv_param_value LIKE ls_post-contract.
ASSIGN lv_param_value->* TO <lv_param_value>.
<lv_param_value> = ls_post-contract.
ls_parameter-value = lv_param_value.
INSERT ls_parameter INTO TABLE lt_parameters.
" Finally, fire the plug.
wd_this->wd_get_api( )->fire_plug( plug_name = lv_source_plug_name parameters = lt_parameters ).
ENDLOOP.
This problem is not limited to dynamic generation of views but also occurs when you want to use a particular view more than once in a window of the same component. Only one instance is created so reuse is very limited.
The only solution to this would be to separate the the View off to its own Web Dynpro component or to create multiple component usages of the active WDC and using those in dynamic navigation.