Header Ads

How to set breadcrumbs in UIU Applications


How to set breadcrumbs in UIU Applications:

Please find below the guidelines based on the implementation done in Service Order Application (UI Component BT116H_SRVO) in order to fulfil the breadcrumb requirements:

In the following the term sync point is used, this means simply a place where we code the “raise event history_trigger” for breadcrumb navigation.

Which sync points do we need (where is raise event history_trigger written)?

According to concept team guidelines we define sync point on search page and on overview page (both header and item level). Currently we do not set this sync points if we are in creation mode i.e. the root object is not yet persistent.

1) Sync Point for Search Page

We write raise event history_trigger in method WD_DESTROY of the ViewSet of the search page (see UI component BT116S_SRVO, View SearchViewSet, Method WD_DESTROY. Do not forget to call also the method from the superclass.

Sample:

METHOD wd_destroy.

  DATA: lr_tcc     TYPE REF TO cl_bt116s_s_bspwdcomponen_impl.

  lr_tcc ?= me->comp_controller.

  IF lr_tcc->gv_write_breadcrumb = abap_true.
    RAISE EVENT history_trigger.
  ENDIF.
  CLEAR lr_tcc->gv_write_breadcrumb.

  CALL METHOD super->wd_destroy.


ENDMETHOD.

What has to be done additionally?

You should remove already existing places where event is raised, so that this does not happen twice during roundtrip e.g. when navigation into overview page was done or during event-call from advance search (create, copy, follow-up)

In our case we faced the problem that the search view is also loaded and removed during creation case or if you start the advance search in value-help mode. In that cases we do not want to raise event history_trigger. To overcome this we added a flag gv_write_breadcrumb in our component controller. This flag is set in corresponding inbound plug of the window (IP_ADVSEARCH) and in the DO_VIEW_INIT_ON_RESTORE method of the window controller.

2) Sync Point for Overview Page

We write raise event history_trigger in method WD_DESTROY of the ViewSet of the overview page both for header and for item.:

Header: See UI componet BT116H_SRVO, View OVViewSet, Method WD_DESTROY. Note, that we are using a generic superclass in our Header overview pages. Do not forget to call also the method from the superclass! Note that we do not raise the event if the root-object is not persistent.

Sample:

METHOD wd_destroy.

  DATA: lr_cn  TYPE REF TO cl_bsp_wd_context_node.
  DATA: lr_ent TYPE REF TO if_bol_bo_property_access.

  FIELD-SYMBOLS: <lr_cn> TYPE ANY.

* get root object from context
  assign me->context->('BTOrder') to <lr_cn>.
  IF <lr_cn> IS ASSIGNED.
    lr_cn  ?= <lr_cn>.
    lr_ent ?= lr_cn->collection_wrapper->get_current( ).
  ENDIF.

  IF cl_crm_uiu_bt_tools=>is_order_persistent( lr_ent ) = abap_true.
    RAISE EVENT history_trigger.
  ENDIF.

  CALL METHOD super->wd_destroy.

ENDMETHOD.

Item: See UI component BT140I_SRVP, View OVViewSet, Method WD_DESTROY. Note, that we use here also a generic superclass for out item overview pages. Do not forget to call also the method from the superclass

Sample:

METHOD wd_destroy.

  DATA: lr_cn  TYPE REF TO cl_bsp_wd_context_node.
  DATA: lr_ent TYPE REF TO cl_crm_bol_entity.

  FIELD-SYMBOLS: <lr_cn> TYPE ANY.

* get root object from context
  ASSIGN me->context->('BTAdminI') TO <lr_cn>.
  IF <lr_cn> IS ASSIGNED.
    lr_cn  ?= <lr_cn>.
    lr_ent ?= lr_cn->collection_wrapper->get_current( ).
  ENDIF.

  IF lr_ent IS BOUND.
    DO 3 TIMES.
      lr_ent = lr_ent->get_parent( ).
    ENDDO.
    IF cl_crm_uiu_bt_tools=>is_order_persistent( lr_ent ) = abap_true.
*     raise event for breadcrumbs
      RAISE EVENT history_trigger.
    ENDIF.
  ENDIF.


  CALL METHOD super->wd_destroy.

ENDMETHOD.


What has to be done additionally?

Like in the advance search you should remove existing coding where raise event history_trigger was done e.g. during navigation or during event calls (create, copy, follow-up).

In order to load the proper order header or order item entity if you navigate back via breadcrumb, it is necessary that you store your current entity in the so called “state container” before leaving your component. If your component is then called again, you use this information in order to restore the proper entities. In our case we can navigate back to the header overview page but also to the item overview page. Therefore we have to store not only the root object (current order) but also the subobject (current item).

This is done in the context class of our Window (see BT116H_SRVO, MainWindow) in following methods, provided by the framework (re-definition required):

In the following method we get the  entity of our current root object (btorder) on our current Item (btadmini) out of the component controller and store this entities in the state container. Note that im_name can contain any naming you like). This method is called if the component is left.

METHOD if_bsp_wd_history_state~state_store.

  DATA: lr_vc  TYPE REF TO cl_bt116h_s_mainwindow_impl,
        lr_cc  TYPE REF TO cl_bt116h_s_bspwdcomponen,
        lr_ent TYPE REF TO cl_crm_bol_entity.

***

  lr_vc  ?= me->owner.
  lr_cc  ?= lr_vc->get_comp_controller( ).
  lr_ent ?= lr_cc->typed_context->btorder->collection_wrapper->get_current( ).
  IF lr_ent IS BOUND.
    state_container->add_item( im_name  = 'CurrentOrder'
                               im_value =  lr_ent ).

  ENDIF.

  lr_ent ?= lr_cc->typed_context->btadmini->collection_wrapper->get_current( ).
  if lr_ent is bound.
    state_container->add_item( im_name  = 'CurrentItem'
                               im_value = lr_ent ).
  endif.


ENDMETHOD.

In the 2nd Method we are receiving the info back which we have stored before. Therefore we get the root object (btorder) and the subobject (btadmini) out of the state container and then pass this entities to our component controller.

METHOD if_bsp_wd_history_state~state_restore.


  DATA: lr_vc  TYPE REF TO cl_bt116h_s_mainwindow_impl,
        lr_cc  TYPE REF TO cl_bt116h_s_bspwdcomponen,
        lr_ent TYPE REF TO cl_crm_bol_entity.

***

  state_container->get_item( EXPORTING im_name  = 'CurrentOrder'
                             IMPORTING ex_value = lr_ent
                             EXCEPTIONS OTHERS = 0 ).

  IF lr_ent IS BOUND.

    lr_vc ?= me->owner.
    lr_cc ?= lr_vc->get_comp_controller( ).
    lr_cc->typed_context->btorder->collection_wrapper->add( iv_entity = lr_ent
                                                            iv_set_focus = abap_true ).

    state_container->get_item( EXPORTING im_name  = 'CurrentItem'
                               IMPORTING ex_value = lr_ent
                               EXCEPTIONS OTHERS = 0 ).

    IF lr_ent IS BOUND.
      lr_cc->typed_context->btadmini->collection_wrapper->find( iv_bo = lr_ent ).
    ENDIF.
  ENDIF.

ENDMETHOD.



What you should also keep in mind:

When writing breadcrumb, there is a callback from framework to the application, we you can control whether this breadcrumb should be written or not. This is done via method IF_BSP_WD_HISTORY_STATE_DESCR~IS_RESTORABLE on View or Window controller level. Via this method we make sure, that only breadcrumbs are written for objects, which are persistent. See below sample from service order (UI component BT116H_SRVO, Window controller)

METHOD if_bsp_wd_history_state_descr~is_restorable.

  DATA: lr_comp    TYPE REF TO cl_bt116h_s_bspwdcomponen_impl,
        lr_current TYPE REF TO if_bol_bo_property_access.

* only write breadcrumb entries in case the order was persisted

  lr_comp ?= me->comp_controller.
  lr_current = lr_comp->typed_context->btorder->collection_wrapper->get_current( ).
  IF lr_current IS BOUND.
    rv_result = cl_crm_uiu_bt_tools=>is_order_persistent( lr_current ).
  ELSE.
    rv_result = abap_false.
  ENDIF.

ENDMETHOD.

As the comment in the method describes, we check , that a breadcrumb is only written, if the current order is already on the database. As we do check this already in the WD_DESTROY method, this is not absolutely required (we had this coding already before the changes).

3) What has to be done in generic components or reuse components?

Those components must not set sync points e.g. during navigation from overview assignment block to edit form/edit list..

Sample: UI component BTPARTNER, View PartnerOV (Partner Assingmentblock in One-Order overview pages – eventhandler method for navigation into edit view):

METHOD eh_onbtn_edit.

  DATA:
    lr_entity      TYPE REF TO if_bol_bo_property_access,
    lr_attributes  TYPE crmst_uiu_partner_attr,
    lr_parent      TYPE REF TO cl_crm_bol_entity.

  lr_entity ?= typed_context->relationname->collection_wrapper->get_current( ).

  CALL METHOD lr_entity->get_properties
    IMPORTING
      es_attributes = lr_attributes.

  lr_parent = lr_attributes-partner_set.

  IF lr_parent->is_locked( ) = abap_false.
    lr_parent->lock( ).
  ENDIF.
  RAISE EVENT history_trigger.                  REMOVE!!!
  op_toedit( ).

ENDMETHOD.

4) What should not be done:

If possible, keep the coding of your DONE/BACK button on your views as it is.

5) Additional Info:

Info from Concept Team about BACK navigation (see slide 6 – 9): : \\dwdf029\CRM_UIU\30_UI_Concept\30_UI_Concept_final\33_Back_Navigation.ppt

Info from Framework about state_store/state_restore methods
\\Dwdf029\crm_uiu\40_Framework\Guidelines\Compo\How to restore a table state.doc
Powered by Blogger.