Asynchronous Saved Search Fetch

I have noticed it could be a nice implementation variant for AJAX queries in WebUI. Everyone has it’s own saved search and everyone would like to know how many items are behind it. (Click a picture below to see how it’s working 🙂 ).

Saves_searches.gif

Implementation

Create Custom Controller

Saved searches are managed within GS_WC_QLINKS component. What we are going to need is a new custom-controller e.g. counter.do.

/wp-content/uploads/2016/02/image003_897018.png


This controller will be called stateless to calculate the number of entries behind each of the saved search.

/wp-content/uploads/2016/02/image005_897019.png

Perform AJAX request


The AJAX request is called right from the view GS_WC_QLINKS/savedsearches.htm.


<%@page language=”abap” %>

<%@extension name=”htmlb” prefix=”htmlb”   %>

<%@extension name=”xhtmlb”   prefix=”xhtmlb” %>

<%@extension name=”thtmlb” prefix=”thtmlb”   %>

<%@extension name=”crm_bsp_ic”   prefix=”crmic” %>

<%@extension name=”bsp” prefix=”bsp”   %>

<%

  DATA  lr_ss_wrapper        TYPE REF TO cl_bsp_wd_collection_wrapper.

  DATA  lr_ss                TYPE REF TO cl_crm_bol_entity.

%>

<thtmlb:overflowContainer verticalScrollbar=”NEVER” >

  <%

  data:   lv_search_id    type string.

  data:   lv_search_name     type string.

  lr_ss_wrapper  = savedsearches->get_collection_wrapper( ).

  lr_ss ?= lr_ss_wrapper->get_first( ).

  If lr_ss  is not bound.

  %>

   <img  class=”th-clr-imgsrc=”<%= CL_THTMLB_UTIL=>GET_DYN_ICON_URL(   EXPORTING iv_icon_name =   CL_THTMLB_UTIL=>GC_ICON_INFOMESSAGE iv_icon_type  = CL_THTMLB_UTIL=>GC_BUTTON_ICON ) %>” />&nbsp;

   <thtmlb:textView text = “<%= otr(CRM_UIU_BT/NORESULT)   %>” />

  <%

  Endif.

  while  lr_ss is bound.

  lv_search_id  = lr_ss->get_property_as_string( iv_attr_name = ‘GUID’ ).

  lv_search_name  = lr_ss->get_property_as_string( iv_attr_name = ‘DESCRIPTION’ ).

  %>

  <thtmlb:link id        = “<%= lv_search_id %>”

               onClick = “GO”

               onClientClick  = “thAdvSearchRegisterEvent(‘GO’)”

               text    = “<%= lv_search_name  %>”

               tooltip = “<%= lv_search_name %>” />

  <%

  lr_ss ?= lr_ss_wrapper->get_next(  ).

  %>

  <br>

    <!– –>

  <script language=”javascript” type=”text/javascript“>

   thtmlbAJAXCall.callBackend(“<%= controller->create_ajax_url(   iv_ss = lv_search_id )   %>”,UpdateSavedSearchCallback);

  </script>

<!–   –>

  <%

  endwhile.

  %>

</thtmlb:overflowContainer>

Build Stateless AJAX URL


Saved search IDs are provided along with the AJAX URL, which is built as shown below.


  method create_ajax_url.
 
     
data: lv_query     type string.
     
data: lv_url       type string.
 
     
” Build Query
     
concatenate lv_query ‘crm_controller=’ me->component_id into lv_query.
 
     
if iv_ss is not initial.
       
concatenate lv_query ‘&saved_search=’ iv_ss into lv_query.
     
endif.
 
     
” Create State – Less URL
     
call method cl_crm_web_utility=>create_url
       
exporting
          iv_bsp_application
= me->application_name
          iv_bsp_page       
= ‘counter.do’
          iv_query          
= lv_query
          iv_in_same_session
= abap_false
          iv_no_cookie      
= space
          iv_cache_busting  
= ‘X’
        receiving
          ev_url            
= lv_url.
 
     
split lv_url at ‘?’ into lv_url lv_query.
 
     
call method runtime->get_url_stateless
       
exporting
          application_name
= me->application_name
          page_name       
= ‘counter.do’
        receiving
          url             
= lv_url.
 
     
concatenate lv_url ‘?’ lv_query into rv_url.
 
   
endmethod.

Process AJAX Requests on the backend

The requests will be processed by our custom controller. There we need two methods: DO_REQUEST and GET_COUNT.

/wp-content/uploads/2016/02/image007_897020.jpg


DO_REQUEST:


  method do_request.
 
     
call method super->do_request.
 
     
” Data
     
data: lv_controller_id    type string.
     
data: lv_saved_search     type string.
     
data: lv_key              type guid_32.
     
data: lr_core             type ref to cl_crm_bol_core.
     
data: lr_shortcut_man     type ref to cl_crm_shortcut_manager.
     
data: lr_shortcut         type ref to cl_crm_bol_entity.
     
data: lt_field_list       type table of crmt_rtd_string_pair.
     
data: ls_field_list       type crmt_rtd_string_pair.
     
data: ls_count            type string.
 
     
” Containers
     
data: lr_writer           type ref to cl_sxml_string_writer.
     
data: lv_json             type xstring.
 
     
” Get URL parameters
      lv_controller_id 
= request->get_form_field( ‘crm_controller’ ).
      lv_saved_search  
= request->get_form_field( ‘saved_search’ ).
 
 
     
” Get Shortcut Data
      lr_core
= cl_crm_bol_core=>get_instance( ).
     
“lr_core->start_up(‘SO2’).                                        ” Needed to avoid ABAP dumps
      lr_core
->start_up(‘ALL’).
 
      lr_shortcut_man
= cl_crm_shortcut_manager=>get_instance( ).
 
     
if lv_saved_search  is not initial and
         lv_controller_id
is not initial.
        lv_key
= lv_saved_search.
        lr_shortcut
= lr_shortcut_man->get_shortcut_by_key( iv_key = lv_key ).
 
       
if lr_shortcut is bound.
 
         
” Get the name
         
concatenate lv_controller_id lv_saved_search into ls_field_listname separated by ‘_’.
         
translate ls_field_listname to upper case.
 
         
” Get the value
          ls_field_list
value = lr_shortcut->get_property_as_string( ‘DESCRIPTION’ ).
 
          ls_count
= get_count( lr_shortcut ).
         
if ls_count is initial.
            ls_count
= ‘?’.
         
endif.
         
concatenate ‘(‘ ls_count ‘)’ into ls_count.
         
condense ls_count nogaps.
 
         
concatenate ls_field_listvalue space ls_count
                
into ls_field_listvalue respecting blanks.
 
       
else.
          ls_field_list
name  = ‘ERROR_IN_SAVED_SEARCH_’.
          ls_field_list
value = ‘NO_OBJECT_’.
       
endif.
     
else.
        ls_field_list
name  = ‘ERROR_IN_SAVED_SEARCH_’.
        ls_field_list
value = ‘NO_GUID_’.
     
endif.
 
 
     
” Collect Response
     
append ls_field_list to lt_field_list.
 
     
“ABAP to JSON
      lr_writer
= cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ).
     
call transformation id source text = lt_field_list[] result xml lr_writer.
      lv_json
= lr_writer->get_output( ).
 
 
     
” Send response
      response
->set_header_field( name = ‘content-type’  value = ‘text/xml’ ).
      response
->set_header_field( name = ‘charset’       value = ‘utf-8’ ).
      response
->set_header_field( name = ‘Pragma’        value = ‘no-cache’ ).
      response
->set_header_field( name = ‘Expires’       value = ‘0’ ).
      response
->set_header_field( name = ‘Cache-Control’ value = ‘max-age=0’ ).
 
     
response->set_data( lv_json ).
 
   
endmethod.

GET_COUNT:


  method get_count.
 
     
data: lr_dquery            type ref to cl_crm_bol_dquery_service.
     
data: id_of_query_template type genil_dquery_handle.
     
data: lr_res_col           type ref to if_bol_entity_col.
 
      rv_count
= .
 
     
check: ir_shortcut is bound.
 
     
try.
          id_of_query_template
= ir_shortcut->get_property_as_string( ‘PARAMETER_’ ).
          lr_dquery
= cl_crm_bol_dquery_service=>load_query_template( iv_query_id =

                                                                     id_of_query_template ).
 
          lr_res_col
= lr_dquery->get_query_result( ).
          rv_count
= lr_res_col->get_iterator( )->size( ).
 
       
catch cx_crm_genil_not_ready.
       
catch cx_sy_no_handler.
       
catch cx_crm_bol_not_ready.
       
catch cx_bol_exception.
     
endtry.
 
   
endmethod.

Writing AJAX call-back function

/wp-content/uploads/2016/02/image008_897021.png

function UpdateSavedSearchCallback(reqObj)

  {

   var responseText = reqObj.request.responseText;

   var obj = JSON.parse(responseText);

   var fnum = obj.TEXT.length;

   for (var i = 0; i < fnum; i++) {

    var elem = document.getElementById(obj.TEXT[i].NAME);

     if (elem){

      elem.title = obj.TEXT[i].VALUE;

      elem.innerHTML  = obj.TEXT[i].VALUE;

     }

   }

  }

Publish a link to the JS file in the table WCFC_ADD_JS.

To report this post you need to login first.

1 Comment

You must be Logged on to comment or reply to a post.

Leave a Reply