Update view fields via AJAX call

Use Case

When doing some applications one may need to update certain fields on the screen without calling a back-end. In this case, the use of AJAX functionality of CRM WebUI can be useful. In this document, we will describe how one can update all the configured fields on the view.

Let us assume we have a view with Order Summary information, including Gross Value, Net Value, Tax Amount, Number of Items and Gross Weight.

/wp-content/uploads/2016/01/image001_877173.png


On BSP level, it look like below:

<%@page language=”abap” %>
 
<%@extension name=”chtmlb” prefix=”chtmlb” %>
 
<%@extension name=”thtmlb” prefix=”thtmlb” %>
 
  <chtmlb:config displayMode =
“FALSE”
                 mode        =
“RUNTIME” />
 
 

Required JavaScript

As described before (see: http://scn.sap.com/community/crm/webclient-ui-framework/blog/2015/12/11/parallelization-in-web-ui–part2), we need a function which calls an AJAX request and the functionality which will be called after the request is executed, i.e. a callback function.

As before, we will be using a standard method thtmlbAJAXCall.callBackendin order to call a back-end handler.

<script language=javascripttype=“text/javascript>
 
  function UpdateTotals()
  {
 
var ajax_url = “<%= controller->create_ajax_url( ) %>”;
  thtmlbAJAXCall.callBackend(ajax_url,UpdateTotalsCallback);
  }


  </script>

In this case, we will use our own callback function, which will be expecting the data in JSON format. Basically it expects a table with two columns: NAME and VALUE. NAME will be a unique id of the field (e.g. C18_W65_V67_V69_btcumulath_struct.gross_value) and VALUE is the text, which needs to be placed into the field.

<script language=javascripttype=“text/javascript>
 
  function UpdateTotalsCallback(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.value = obj.TEXT[i].VALUE;
     }
   }
  }
 
 

</script>

Required ABAP code

For consistency we also place a full ABAP code, including the one needed to generate the AJAX URL.

method create_ajax_url.
 
   
data: lr_class_desc    type ref to cl_abap_typedescr.
   
data: lv_class_name    type string.
 
    lr_class_desc
= cl_abap_classdescr=>describe_by_object_ref( me ).
    lv_class_name
= lr_class_desc->get_relative_name( ).
 
   
call method cl_crm_web_utility=>create_service_url
     
exporting
        iv_handler_class_name
= lv_class_name
        iv_controller_id     
= me->component_id
      receiving
        ev_url               
= rv_url.
 
 
endmethod.

Below you can find a sample of callback handler.

  method if_crm_web_callback~handle_request.
 
     
data: lr_controller      type ref to zl_zdmsh_pr_totals_impl.
     
data: lr_model           type ref to if_bsp_model_binding.
     
data: lr_context_node    type ref to cl_bsp_wd_context_node.
     
data: lr_descr           type ref to if_bsp_dlc_view_descriptor.
     
data: lv_xml             type bsp_dlc_xml.
     
data: lt_bsp_fields      type bsp_dlct_adv_conf_itm.
     
data: lt_field_list      type table of crmt_rtd_string_pair.
 
     
data: lv_node            type string.
     
data: lv_attribute_path  type string.
 
     
data: lr_writer          type ref to cl_sxml_string_writer.
     
data: lv_json            type xstring.
 
 
     
field-symbols:
        <fs_bsp_field
type bsp_dlcs_adv_conf_itm,
        <fs_field_list>
type crmt_rtd_string_pair.
 
 
     
check ir_controller is bound.
 
     
try.
          lr_controller ?= ir_controller
.
       
catch cx_root.
     
endtry.
 
     
check lr_controller is bound.
 
     
” Get Personalization
      lr_descr
= lr_controller->configuration_descr->get_property_descriptor( ).
      lv_xml  
= lr_controller->configuration_descr->get_config_data( ).
 
     
” Get Available BSP Fields
     
call method cl_bsp_dlc_config_util=>adv_conf_meta_to_table
       
exporting
          ir_view_descr       
= lr_descr
          iv_adv_conf_meta_xml
= lv_xml
       
importing
          et_adv_conf         
= lt_bsp_fields.
 
     
” Loop At BSP Fields
     
loop at lt_bsp_fields assigning <fs_bsp_field> where type = ‘FIELD’.
 
       
” Get Model Data
       
call method cl_bsp_model=>if_bsp_model_util~split_binding_expression
         
exporting
            binding_expression
= <fs_bsp_field>field_name
         
importing
            attribute_path    
= lv_attribute_path      ” Property
            model_name        
= lv_node.               ” Context Node
 
       
try.
           
” Get BSP Model
            lr_model ?= ir_controller
->get_model( lv_node ).
 
           
” Check Context Node
            lr_context_node  ?= lr_model
.
 
           
append initial line to lt_field_list assigning <fs_field_list>.
 
            <fs_field_list>
name  = lr_model->get_attribute_name( lv_attribute_path ).
            <fs_field_list>
value = lr_model->get_attribute( attribute_path = lv_attribute_path ).
 
         
catch: cx_root.
           
continue.
       
endtry.
 
     
endloop.
 
     
“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( ).
 
 
     
” Set Response
      ir_server
->response->set_data( lv_json ).
      ir_server
->response->set_header_field( name  = ‘content-type’
                                            
value = ‘text/xml’ ).
 
 
   
endmethod.

One can note that our coding (we are talking about ABAP and JavaScript together) is very generic. It does not depend on the selected model and context nodes. It is also performance and logically optimized, as we are processing only the fields, which are present on the screen (as per WebUI configuration), and not the possible ones.

Hope it can help someone to build modern usability- and performance- optimized applications in WebUI.

To report this post you need to login first.

Be the first to leave a comment

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

Leave a Reply