2

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.
Sandra Rossi
  • 11,934
  • 5
  • 22
  • 48
Lilienthal
  • 4,327
  • 13
  • 52
  • 88

1 Answers1

2

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.

Lilienthal
  • 4,327
  • 13
  • 52
  • 88
  • Could you please provide an example code? We tried your solution without success. – Dorad Apr 09 '18 at 12:14
  • @Dorad I'm afraid I can't. This is nearly four years old and not only do I no longer have access to the system this was set up in, IIRC I never actually solved the original problem but rather worked around it. As mentioned in this answer the real solution would likely be creating component usages as well and passing those along but I suspect it's a chore to code and a nightmare to maintain and I never actually tested it. Frankly at this point trying to do anything even remotely this complex in WD is a sign that you should be moving to Fiori. If you have to use it, I'd suggest a new question. – Lilienthal Apr 09 '18 at 20:24