In NET311 the topic component usage clone is discussed there. One example is also given there:
The user of a Web Dynpro application can mark multiple lines of a table to display details for each selected data set. The details of one data set is displayed by one usage of a certain component. Thus, the number of component usages equals the number of marked lines, which is not known at design time.
The prerequisite for cloning any component usage is, that a single usage of this component has been defined at design time. Any controller having added the name of the static component usage to the list of used controllers / components can then create additional usages of the same component. Each component usage must have a unique name.
I will reuse the component created in the blog Step by Step to create UI elements and context node attribute in the runtime . After I maintain the content number and click create button, the label and text view together with their bound context node attribute will be generated in the runtime. The value of text view “Echo from Usage clone:<number>” is returned by the cloned component usage.
(1) Create a simple component ZDYNAMICUSAGE which will be consumed as component usage later. Implement the echo method in component controller.
(2) In order to use component usage, there must be at least one static component usage.Also define usage of the interface controller in the consumer view controller.
(3) In method CREATE_CONTEXT, just enhance one line. ( In the original example, I just set the value of newly-generated context attribute to its attribute name)
method CREATE_CONTEXT . CONSTANTS: cv_value type string value 'VALUE'. data(lo_node) = wd_context->get_child_node( 'DYNAMIC' ). data(lo_node_info) = lo_node->get_node_info( ). data(lt_attributes) = lo_node_info->get_attributes( ). DO iv_count TIMES. DATA(lv_attribute_name) = cv_value && sy-index. READ TABLE lt_attributes WITH KEY name = lv_attribute_name TRANSPORTING NO FIELDS. IF sy-subrc <> 0. data(ls_attribute_prop) = VALUE wdr_context_attribute_info( NAME = lv_attribute_name TYPE_NAME = 'STRING' ). lo_node_info->add_attribute( attribute_info = ls_attribute_prop ). DATA(lv_value) = wd_this->get_value_by_index( sy-index ). lo_node->set_attribute( name = lv_attribute_name value = lv_value ). ENDIF. ENDDO. endmethod.
(4) Define one attribute in view controller, which is an internal table to store all references of component usage instance.
In view controller WDDOINT, insert the static component usage to the internal table. The internal table would have the first line as static component usage instance and all remaining ones for cloned component usage from the static one.
method WDDOINIT . DATA(lo_static_usage) = wd_this->wd_cpuse_zclone_example( ). APPEND lo_static_usage TO wd_this->gt_cmp_usages. endmethod.
(5) Implement the method get_value_by_index which is called in step3. I will read the internal table gt_cmp_usages by index. Index 1 means this is a static component usage so I directly use the one return from wd_this->wd_cpuse_zclone_example( ). Or else the left one will be cloned from the static one. Since the usage name should be unique, so I use a prefix and an index to fulfill the uniqueness.
method GET_VALUE_BY_INDEX . DATA(lo_static_com_usage) = wd_this->wd_cpuse_zclone_example( ). DATA: lo_generic_usage TYPE REF TO if_wd_component_usage, lo_interface_control TYPE REF TO ZIWCI_DYNAMICUSAGE. READ TABLE wd_this->gt_cmp_usages ASSIGNING FIELD-SYMBOL(<usage>) INDEX iv_index. CASE iv_index. WHEN 1. IF lo_static_com_usage->has_active_component( ) IS INITIAL. lo_static_com_usage->create_component( ). ENDIF. lo_generic_usage = lo_static_com_usage. WHEN OTHERS. READ TABLE wd_this->gt_cmp_usages ASSIGNING FIELD-SYMBOL(<dyn_usage>) INDEX iv_index. IF sy-subrc <> 0. DATA(lv_usage_name) = 'DYNAMIC_USAGE' && sy-index. data(lo_dyn_usage) = lo_static_com_usage->create_comp_usage_of_same_type( name = lv_usage_name ). APPEND lo_dyn_usage TO wd_this->gt_cmp_usages. ENDIF. IF lo_dyn_usage->has_active_component( ) IS INITIAL. lo_dyn_usage->create_component( ). ENDIF. lo_generic_usage = lo_dyn_usage. ENDCASE. lo_interface_control ?= lo_generic_usage->get_interface_controller( ). rv_output = lo_interface_control->get_field_value( iv_index ). endmethod.
In the debugger I would observe that every component usage in gt_cmp_usages are unique: