이글은 아래 링크의 원본 글에 대한 한글 번역 입니다

https://blogs.sap.com/2013/11/20/dynamic-ui-generation-in-web-dynpro-abap/

 

 

 

웹딘프로아밥에서 동적 UI 생성

이글은 웹딘프로아밥에서 동적으로 뷰를 생성하는 방법을 설명한 글입니다.

Author : Raj

Raj is an Application Developer focusing on Custom Development - particularly in the areas of ABAP ,WD4A , JAVA , APO , Enterprise services and PI Developer/consultant . He is also certified in ABAP and PI. FacebookTwitter

 

 

아우 씨* 이건 멍미!! 아래 그림의 웹딘프로아밥 뷰 레이아웃을 본 나의 첫 한마디 입니다.

실행 결과는 이렇습니다:

그날은 내가 처음으로 우리 멋진 팀장님으로 부터 동적 UI 생성에 대해서 전해들었습니다. 이런 이야기 입니다.

웹딘프로아밥에는 각 UI 엘리먼트 마다 클래스(예: CL_WD_CHECKBOX , CL_WD_CHECKBOX_GROUP, CL_WD_INPUT_FIELD 등)가 하나씩 있습니다. 이 클래스를 이용하면 뷰의 WDDOMODIFYVIEW 메소드에서 UI 엘리먼트를 뷰에 추가 할 수 있습니다.

간단한 예제로 뷰에 트레이 UI 엘리먼트를 만들어 보겠습니다.

 

예제 1:

뷰에 트레이 UI 엘리먼트 만들기.

정답:

티코드 SE80에서 웹딘프로아밥 컴포넌트를 하나 만듭니다. MAIN 뷰에 transparent container 아이디 TC_MAIN을 만들고 flow 레이아웃으로 지정합니다. ( 이렇게 transparent container를 만드는게 필수는 아니지만 transparent container가 있으면 나중에 뷰를 조정할때 도움이 됩니다. 그러므로 transparent container를 만들기를 추천합니다)

모든 동적 생성 UI 엘리먼트는 이 transparent container에 배치할 것입니다.

아래 소스코드를 뷰의 WDDOMODIFYVIEW 메소드에 입력하면 트레이 UI 엘리먼트가 준비됩니다.

method WDDOMODIFYVIEW .
 "Let's Create Tray
 data : lr_tray type REF TO cl_wd_tray.
 data : lr_caption TYPE REF TO cl_wd_caption.
 DATA : lr_container  TYPE REF TO cl_wd_uielement_container.
 data : lr_flow type ref to cl_wd_flow_data.
 data : lr_matrix_layout type REF TO cl_wd_matrix_layout.
 
 "As we are gonna put the tray in TC_MAIN ( the transperant container )
 "fetch it ...
 lr_container ?= view->get_element( 'TC_MAIN' ).
 
 "Create a Tray Object
 CALL METHOD CL_WD_TRAY=>NEW_TRAY
 EXPORTING
 ID      = 'TR_TRAY'
 WIDTH   = '100%'
 RECEIVING
 CONTROL = lr_tray.
 
 
 "Need to Assign the flow layout information for this Tray
 "As it is part if ROOTUIELEMENTCONTAINER ( with layout flow )
 lr_flow = cl_wd_flow_data=>new_flow_data( lr_tray ).
 
 lr_tray->set_layout_data( lr_flow ).
 "" add tray to container
 CALL METHOD lr_container->add_child
 EXPORTING
 the_child = lr_tray.
 
 "' set layout of tray
 CALL METHOD cl_wd_matrix_layout=>new_matrix_layout
 EXPORTING
 container = lr_tray
 RECEIVING
 control   = lr_matrix_layout.
 
 CALL METHOD cl_wd_caption=>new_caption
 EXPORTING
 id      = 'CA_TRAY'
 text    = 'Yahoo... Here is my Tray (*_*)'
 RECEIVING
 control = lr_caption.
 
 "' set header for tray
 CALL METHOD lr_tray->set_header
 EXPORTING
 the_header = lr_caption.
 
 endmethod.

 

저장하고 활성화하고 실행합니다.

 

예제 2:

트레이 안에 input field 와 label 그리고 button을 추가합니다.

정답:

input field 의 Value 속성은 반드시 컨텍스트의 어트리뷰트가 바인딩 되어야 합니다. 그러므로 컨택스트 노드/어트리뷰트를 먼저 만들어야 합니다.

컴포넌트 컨트롤러에 RET_CC_CONTEXT 메소드를 만듭니다.

Exporting parameter : ER_CONTEXT  type ref to IF_WD_CONTEXT_NODE.

 

아래 소스 코드를 WDDOMODIFYVIEW 메소드에 입력하고 다시 실행해보세요. 만약 활성화할때 에러가 발생한다면 에러 메시지를 보고 스스로 해결하도록 합니다.

method WDDOMODIFYVIEW .
 "Let's Create Tray
 data : lr_tray type REF TO cl_wd_tray.
 data : lr_caption TYPE REF TO cl_wd_caption.
 DATA : lr_container  TYPE REF TO cl_wd_uielement_container.
 data : lr_flow type ref to cl_wd_flow_data.
 data : lr_matrix_layout type REF TO cl_wd_matrix_layout.
 
 "As we are gonna put the tray in TC_MAIN ( the transperant container )
 "fetch it ...
 lr_container ?= view->get_element( 'TC_MAIN' ).
 
 "Create a Tray Object
 CALL METHOD CL_WD_TRAY=>NEW_TRAY
 EXPORTING
 ID      = 'TR_TRAY'
 WIDTH   = '100%'
 RECEIVING
 CONTROL = lr_tray.
 
 
 "Need to Assign the flow layout information for this Tray
 "As it is part if ROOTUIELEMENTCONTAINER ( with layout flow )
 lr_flow = cl_wd_flow_data=>new_flow_data( lr_tray ).
 
 lr_tray->set_layout_data( lr_flow ).
 "" add tray to container
 CALL METHOD lr_container->add_child
 EXPORTING
 the_child = lr_tray.
 
 "' set layout of tray
 CALL METHOD cl_wd_matrix_layout=>new_matrix_layout
 EXPORTING
 container = lr_tray
 RECEIVING
 control   = lr_matrix_layout.
 
 CALL METHOD cl_wd_caption=>new_caption
 EXPORTING
 id      = 'CA_TRAY'
 text    = 'Yahoo... Here is my Tray (*_*)'
 RECEIVING
 control = lr_caption.
 
 "' set header for tray
 CALL METHOD lr_tray->set_header
 EXPORTING
 the_header = lr_caption.
 
 
 "****************Create Input field ********************************
 "create Node And Element for input field
 "Part 1: stracture creation : with one field called name
 TYPE-POOLS:  abap.
 
 DATA :
 lt_components     TYPE abap_component_tab,
 lw_component      TYPE LINE OF abap_component_tab,
 lr_structdescr    type ref to CL_ABAP_STRUCTDESCR,
 lt_attribs TYPE  wdr_context_attr_info_map,
 ls_attribs like LINE OF lt_attribs.
 
 
 lw_component-name = 'NAME'.
 TRY.
 lw_component-type = cl_abap_elemdescr=>get_c(  p_length =  20 ).
 CATCH cx_sy_move_cast_error .
 ENDTRY.
 
 append lw_component to lt_components.
 
 lr_structdescr = cl_abap_structdescr=>create( lt_components ).
 "Part2 : Now Create a Node based on this Dynamic struct.
 
 DATA:
 lo_parent_node_info                TYPE REF TO if_wd_context_node_info,
 lo_child_node_info                 TYPE REF TO if_wd_context_node_info,
 *    lo_nd_gen_tab                      TYPE REF TO if_wd_context_node,
 lt_child_node_map                  TYPE wdr_context_child_info_map,
 comp_context type ref to if_wd_context_node.
 FIELD-SYMBOLS : <fs_stru>    TYPE any .
 *  DATA   dy_stru       TYPE REF TO data.
 
 wd_comp_controller->ret_cc_context(
 IMPORTING
 er_context = comp_context ).
 
 lo_parent_node_info = comp_context->get_node_info( ).
 lt_child_node_map = lo_parent_node_info->get_child_nodes( ).
 READ TABLE lt_child_node_map TRANSPORTING NO FIELDS WITH TABLE KEY name = 'ND_DETAIL'.
 IF sy-subrc = 0.
 " REMOVE_CHILD_NODE
 lo_parent_node_info->remove_child_node(  'ND_DETAIL' ).
 ENDIF.
 
 "" get attrib property
 LS_ATTRIBS-name = 'NAME'.
 insert ls_attribs into table lt_attribs.
 
 " create Node in Comp Controller
 CALL METHOD lo_parent_node_info->add_new_child_node
 EXPORTING
 name                         = 'ND_DETAIL'
 is_singleton                 = abap_true
 static_element_rtti          = lr_structdescr
 is_static                    = abap_true
 attributes                   = lt_attribs
 RECEIVING
 child_node_info              = lo_child_node_info.
 
 
 DATA lr_wa            TYPE REF TO data.
 data lo_child_node_detail TYPE ref to if_wd_context_node.
 FIELD-SYMBOLS <lfs_dyn> TYPE any.
 CREATE DATA lr_wa TYPE HANDLE lr_structdescr.
 ASSIGN lr_wa->* TO <lfs_dyn>.
 lo_child_node_detail = comp_context->get_child_node( name = 'ND_DETAIL' ).
 lo_child_node_detail->bind_structure( EXPORTING new_item =   <lfs_dyn> ).
 
 " Map that component controller node to View
 
 DATA: lo_node_info TYPE REF TO if_wd_context_node_info,
 lo_node TYPE REF TO if_wd_context_node,
 mapping_info TYPE wdr_context_mapping_info,
 lv_name TYPE string,
 lt_path TYPE wdr_ctx_element_path_segments.
 DATA map_path TYPE string.
 CLEAR lt_path.
 
 ""
 DATA:
 lr_child_node_info_view                 TYPE REF TO if_wd_context_node_info,
 lt_child_node_map_view                 TYPE wdr_context_child_info_map.
 lo_node_info  = WD_CONTEXT->get_node_info( ).
 lv_name = 'ND_DETAIL'.
 lt_child_node_map_view  = lo_node_info->get_child_nodes( ).
 READ TABLE lt_child_node_map TRANSPORTING NO FIELDS WITH TABLE KEY name = 'ND_DETAIL'.
 IF sy-subrc = 0.
 " REMOVE_CHILD_NODE
 lo_node = wd_context->get_child_node(  name = 'ND_DETAIL' ).
 lr_child_node_info_view = lo_node->get_node_info( ).
 RETURN.
 ELSE.
 ENDIF.
 
 CONCATENATE 'COMPONENTCONTROLLER.' lv_name INTO map_path.
 APPEND map_path TO lt_path.
 mapping_info-controller = 'COMPONENTCONTROLLER'. "conponent name
 mapping_info-path = lt_path. "Controller context node name
 "" create view node refering component node
 CALL METHOD lo_node_info->add_new_mapped_child_node
 EXPORTING
 child_name      = lv_name
 mapping_info    = mapping_info
 is_static       = abap_true
 RECEIVING
 child_node_info = lr_child_node_info_view.
 
 
 "Now Let's Create An input field along with the label and put it in Try
 "Bind the inout field with the Name element of ND_DETAIL Node we created
 
 DATA lr_input  TYPE REF TO cl_wd_input_field..
 DATA lr_matrix_data    TYPE REF TO cl_wd_matrix_data.
 DATA lr_matrix    TYPE REF TO cl_wd_matrix_head_data.
 DATA lv_lbl_id TYPE string.
 DATA lv_lbl_txt TYPE string.
 DATA lv_lbl_for TYPE string.
 DATA lr_label     TYPE REF TO cl_wd_label.
 DATA inp_id TYPE string.
 DATA lv_width TYPE string.
 CLEAR  : inp_id , lv_width.
 
 CALL METHOD cl_wd_input_field=>new_input_field
 EXPORTING
 bind_value             = 'ND_DETAIL.ND_DETAIL.NAME'
 id                     = 'IF_NAME'
 input_prompt           = 'Enter Name'
 RECEIVING
 control                = lr_input.
 
 "" create lbl for Input field
 CALL METHOD cl_wd_label=>new_label
 EXPORTING
 id        = 'LBL_NAME'
 label_for = 'IF_NAME'
 text      = 'Name'
 RECEIVING
 control   = lr_label. " CONTROL
 
 lr_matrix = cl_wd_matrix_head_data=>new_matrix_head_data( lr_label ).
 lr_label->set_layout_data( lr_matrix ).
 
 lr_matrix_data = cl_wd_matrix_data=>new_matrix_data( lr_input ).
 lr_input->set_layout_data( lr_matrix_data ).
 
 "Let's Add this couple to the Try
 
 "' get tray as container
 lr_container ?= view->get_element( 'TR_TRAY' ).
 
 
 "" add label and Input field to Tray
 CALL METHOD lr_container->add_child
 EXPORTING
 the_child = lr_label.
 CALL METHOD lr_container->add_child
 EXPORTING
 the_child = lr_input.
 
 "Now let's Create a button and add it to Tray
 data : lr_button type REF TO cl_wd_button.
 
 CALL METHOD CL_WD_BUTTON=>NEW_BUTTON
 EXPORTING
 IMAGE_SOURCE           = '~Icon/Search'
 on_action              = 'PROCESS_EVENT'
 ID                     = 'BTN_SEARCH'
 TEXT                   = 'Sumit'
 RECEIVING
 CONTROL                 = lr_button.
 
 "as we want this button to come on new line make it matrix head data
 
 lr_matrix = cl_wd_matrix_head_data=>new_matrix_head_data( lr_button ).
 lr_button->set_layout_data( lr_matrix ).
 
 "" add Button to Tray
 CALL METHOD lr_container->add_child
 EXPORTING
 the_child = lr_button.
 
 endmethod.

 

저장하고 활성화하고 실행합니다.

 

덕후들을 위한 추가…

예제 3:

SEARCH 버튼을 누르면 팝업화면에 입력한 이름을 표시합니다.

힌트: Search 버튼에 바인딩된 액션 메소드 ONACTIONPROCESS_EVENT 를 구현해야 합니다.

하다가 문제가 있으면 댓글로 질문주세요 ..

해피 코딩….

 

 

이글은 아래 링크의 원본 글에 대한 한글 번역 입니다

https://blogs.sap.com/2013/11/20/dynamic-ui-generation-in-web-dynpro-abap/

+ Recent posts