Skip to Content
Author's profile photo Dmitrii Sharshatkin

Asynchronous Saved Search Fetch

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.

Assigned Tags

      1 Comment
      You must be Logged on to comment or reply to a post.
      Author's profile photo Samuel Irvine
      Samuel Irvine

      Thank you. Very helpful indeed.

      Regards,

      Sam