abapalv

Unable to expand single node using cl_salv_tree


I create an ALV Tree with the class cl_salv_tree and want to expand a single node which is the parent to all other nodes and simultaneously the first one to be created. I use the following code:

REPORT.
TYPES: BEGIN OF ty_kennzahlen,
         beber TYPE t357-beber,
         fing  TYPE t357-fing,
       END OF ty_kennzahlen.
DATA: go_tree       TYPE REF TO cl_salv_tree,
      gr_node       TYPE REF TO cl_salv_node,
      gr_nodes      TYPE REF TO cl_salv_nodes,
      gr_main_key   TYPE lvc_nkey,
      gt_kennzahlen TYPE STANDARD TABLE OF ty_kennzahlen,
      lv_bebertext  TYPE t357.
PARAMETERS dummy.

AT SELECTION-SCREEN OUTPUT.
  IF go_tree IS NOT BOUND.
    CALL METHOD cl_salv_tree=>factory
      EXPORTING
        r_container = cl_gui_container=>screen0
      IMPORTING
        r_salv_tree = go_tree
      CHANGING
        t_table     = gt_kennzahlen.
    gr_nodes = go_tree->get_nodes(  ).
    gr_node = gr_nodes->add_node(
             related_node   = ''  " Schlüssel zum verwanten Knoten
             relationship   = cl_gui_column_tree=>relat_last_child   " Knotenrelationen im Tree
             collapsed_icon = CONV #( icon_closed_folder )
             expanded_icon  = CONV #( icon_open_folder )
             row_style      = if_salv_c_tree_style=>intensified
             text           = CONV #( 'Gesamt'(012) ) ).         " ALV-Control: Zelleninhalt
    gr_main_key = gr_node->get_key( ).
*Children of the parentnode:
    DATA(lt_kennzahlen) = VALUE string_table( ( `Child 1` ) ( `Child 2` ) ).
    LOOP AT lt_kennzahlen INTO DATA(lv_bebertext).
      gr_node = gr_nodes->add_node(
          related_node   = gr_main_key  " Schlüssel zum verwanten Knoten
          relationship   = cl_gui_column_tree=>relat_last_child   " Knotenrelationen im Tree
          collapsed_icon = CONV #( icon_closed_folder )
          expanded_icon  = CONV #( icon_open_folder )
          row_style      = if_salv_c_tree_style=>intensified
          text           = CONV #( lv_bebertext ) ).         " ALV-Control: Zelleninhalt
    ENDLOOP.
    gr_nodes = go_tree->get_nodes( ).
    gr_node = gr_nodes->get_node( node_key = gr_main_key ).
    gr_node->expand(  EXPORTING complete_subtree = abap_true  ).
    go_tree->get_tree_settings( )->set_hierarchy_size( 50 ).
    go_tree->display( ).
  ENDIF.

Solution

  • Here is my OOTB snippet based on standard tables:

    CLASS lcl_tree DEFINITION.
    PUBLIC SECTION.
      CLASS-DATA:
        go_alv_tree  TYPE REF TO cl_salv_tree,
        gt_empty_tab TYPE STANDARD TABLE OF spfli,
        gt_full_tab  TYPE STANDARD TABLE OF spfli.
      CLASS-METHODS:
        create_tree.
    ENDCLASS.
    
    CLASS lcl_tree IMPLEMENTATION.
    METHOD create_tree.
      TRY.
          cl_salv_tree=>factory(
            IMPORTING
              r_salv_tree = go_alv_tree
            CHANGING
              t_table     = gt_empty_tab ).
        CATCH cx_salv_error.
          MESSAGE 'ALV creation error' TYPE 'E'.
      ENDTRY.
    
      DATA(lo_settings) = go_alv_tree->get_tree_settings( ).
      lo_settings->set_hierarchy_size( 50 ).
      lo_settings->set_hierarchy_icon( CONV salv_de_tree_image( icon_tree ) ).
      DATA(lo_nodes) = go_alv_tree->get_nodes( ).
    
      SELECT * FROM spfli INTO TABLE gt_full_tab ORDER BY carrid.
      LOOP AT gt_full_tab ASSIGNING FIELD-SYMBOL(<fs_line>).
        TRY.
            AT NEW carrid.
              DATA(lo_node) = lo_nodes->add_node( related_node = ''
                                                  relationship   = cl_gui_column_tree=>relat_last_child
                                                  data_row       = <fs_line>
                                                  row_style      = if_salv_c_tree_style=>emphasized_a
                                                  text           = 'Parent node' ).
              DATA(lv_carrid_key) = lo_node->get_key( ).
            ENDAT.
            AT NEW connid.
              lo_node = lo_nodes->add_node( related_node = lv_carrid_key
                                            relationship   = cl_gui_column_tree=>relat_last_child
                                            data_row       = <fs_line>
                                            row_style      = if_salv_c_tree_style=>emphasized_negative
                                            text           = 'Child node' ).
            ENDAT.
          CATCH cx_salv_msg INTO DATA(exc).
        ENDTRY.
      ENDLOOP.
    * !!!this is the stuff the does the things !!!*
      WHILE go_alv_tree->get_nodes( ) IS BOUND.
        lo_node = go_alv_tree->get_nodes( )->get_node( node_key = lv_carrid_key ).
        CHECK lo_node IS BOUND.
        lo_node->expand( ).
        lo_node = lo_nodes->add_node( related_node = lv_carrid_key
                                      relationship   = cl_gui_column_tree=>relat_last_child
                                      data_row       = <fs_line>
                                      row_style      = if_salv_c_tree_style=>emphasized_c
                                      text           = 'I am the node added on-the-fly' ).
        EXIT.
      ENDWHILE.
    ENDMETHOD.                    "create_tree
    ENDCLASS.                    "lcl_tree IMPLEMENTATION
    
    START-OF-SELECTION.
    
    lcl_tree=>create_tree( ).
    lcl_tree=>go_alv_tree->display( ).
    

    Pay attention on the WHILE block at the end of the method: it does the expanding of the (always last) node by the key saved in the previous loop and adds the additional child node just after expanding.

    This is what I was referring to when saying "you can't just expand the node in the same loop". Your LOOP AT lt_kennzahlen that creates the nodes cannot be used for expanding them, 'cause the frontend is not updated immediately. That 's why we need separate WHILE loop.

    Why it is always last? Because we save it in every iteration so it stores the last value always, to get the root node use the GET_PARENT( ) method.