Skip to Content

I have already briefly mentioned asynchronous rendering of the tables here:

Parallelization in Web UI – Part 2

Since then I have simplified a solution to a certain extent, but I forgot to make a post about it ūüôā . A new solution does not require you to use createFastRowsCallback function (which, in fact, should receive a kind of crazy input, that you have to create on your own).

Instead we will build a normal HTML-based response. It can be doe for ANY Tajax area, including the tables.

So, what is the difference?

And the changes are:

1.¬†¬†¬†¬†¬†¬† When building a view, we start it from our own TAJAX area (<tajax:areaid=”myTajaxArea” >).

2.       Moreover, we need to store its name in the controller class (controller->gr_ajax_area = page_context->element_at_top_of_stack( ).).

3.       As a callback function, we are using our own one. (function UpdateMyTable(reqObj)).

<%@page language=”abap” %>
<%@extension name=”thtmlb” prefix=”thtmlb” %>
<%@extension name=”chtmlb” prefix=”chtmlb” %>
<%@extension name=”bsp” prefix=”bsp” %>
<%@extension name=”tajax” prefix=”tajax” %>
<script language=
javascripttype=“text/javascript>
function UpdateMyTable(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.innerHTML = obj.TEXT[i].VALUE;
}
}
}
</script>
<tajax:area id=
myTajaxArea>
</br>
<b>Here the
area begins!</b>
</br>
<%
” Save Top AJAX Area Reference
controller
->gr_ajax_area = page_context->element_at_top_of_stack( ) .

Conversion Cnode SelectionMode to Tag
data: lv_cellerator_selectionmode type string,
lv_cellerator_editmode  type
string,
lv_cellerator_selectioncolumn
type string.
cl_thtmlb_util
=>translate_selection_mode(
exporting
iv_selection_mode   
= SOMEDATA->SELECTION_MODE
iv_all_rows_editable
= space
importing
ev_selection_mode  
= lv_cellerator_selectionmode
ev_edit_mode       
= lv_cellerator_editmode
ev_selection_column
= lv_cellerator_selectioncolumn ).

data: lv_table_bee type ref to cl_chtmlb_config_cellerator.

if controller->gv_config_table is initial
or 1 = 1.

” Create Table
call method cl_chtmlb_config_cellerator=>factory
exporting
id                    = controller->gc_table_id
downloadToExcel      
= ‘TRUE’
editMode             
= ‘NONE’ lv_cellerator_editmode
onRowSelection       
= ‘select’
personalizable       
= ‘TRUE’
selectedRowIndex     
= somedata->selected_index
selectedRowIndexTable
= somedata->selection_tab
selectionColumn      
= lv_cellerator_selectioncolumn
selectionMode        
= lv_cellerator_selectionmode
table                 = somedata->table
_table               
= ‘//SOMEDATA/Table’
usage                
= ‘EDITLIST’
visibleFirstRow      
= somedata->visible_first_row_index
visibleRowCount      
= ‘6’
width                
= ‘100%’
xml                  
= controller->configuration_descr->get_config_data( )
receiving
element      
= lv_table_bee.

Store the link
controller
->gv_config_table ?= lv_table_bee.

”¬†¬† Post AJAX call to update content¬† %>

¬†¬†¬†¬†¬† <script type=“text/javascript>
thtmlbAJAXCall.callBackend(
“<%= controller->create_ajax_url( ) %>”,UpdateMyTable);
</script>
<%

lv_table_bee
->emptytabletext =

¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬†¬† cl_wd_utilities=>get_otr_text_by_alias( ‘CRM_BSP_UI_FRAME_RECOBJ/LOADING’ ).

endif.

” Get the link
lv_table_bee ?= controller
->gv_config_table.

” Render html element
lv_table_bee
->if_bsp_bee~render( _m_page_context ).
%>
</br>
<b>Here the
area ends!</b>
</br>
</tajax:area>

4.       In IF_CRM_WEB_CALLBACK~HANDLE_REQUEST method we are using a new method CREATE_TABLE_VIEW_HTML_NEW, which returns an inner HTML of our TAJAX Area.

method create_table_view_html_new.

 

” Variables

data: lv_attribute_path type string,

lv_model_name     type string.

 

” Strucures

data: ls_area_content type crms_tajax_area_content.

 

” References

data: lo_page            type ref to cl_bsp_ctrl_adapter,

lo_view_manager    type ref to cl_bsp_wd_view_manager,

lo_view_controller type ref to cl_bsp_wd_view_controller,

lo_model           type ref to if_bsp_model_binding,

lo_context_node_tv type ref to cl_bsp_wd_context_node_tv.

 

” Field symbols

field-symbols: <fs_page>  type bsprtip.

 

” Create page instance

read table cl_bsp_context=>c_page_instances

with key page_name = cl_bsp_wd_appl_controller=>appl_controller_name

assigning <fs_page>.

 

” Rendering

if sysubrc is initial and <fs_page>instance is bound.

lo_page            ?= <fs_page>instance.

lo_view_manager    ?= lo_page->m_adaptee.

lo_view_controller ?= ir_controller.

lo_view_manager->render( iv_root_view = lo_view_controller ).

endif.

 

” Get model

call method cl_bsp_model=>if_bsp_model_util~split_binding_expression

exporting

binding_expression = iv_binding_string

importing

attribute_path     = lv_attribute_path

model_name         = lv_model_name.

try.

lo_model ?= ir_controller->get_model( lv_model_name ).

lo_context_node_tv ?= lo_model.

catch: cx_root.

exit.

endtry.

 

“Build table

lo_context_node_tv->build_table( ).

 

” Get AJAX Area Content By ID

call method lo_view_controller->retrieve_ajax_area_content

exporting

iv_page_id         = ir_controller->component_id

iv_area_id         = iv_ajax_area_id

importing

es_content_info    = ls_area_content

er_used_controller = lo_view_controller.

 

ev_html = ls_area_contentarea_content.

 

 

endmethod.

 

 

5.       We send back this inner HTML code as a part of JSON response. (Here we use a table, as probably several areas or individual fields can be processed in one request).


call method create_table_view_html_new
exporting
ir_server        
= ir_server
ir_controller    
= ir_controller
iv_binding_string
= ‘//SOMEDATA/TABLE’
iv_ajax_area_id  
= lr_controller->gr_ajax_area->id
importing
ev_html          
= lv_html.

if lv_html is not initial.
ls_field_list
name  = lr_controller->gr_ajax_area->id.
ls_field_list
value = lv_html.
append ls_field_list to lt_field_list.
endif.

“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’ ).

And the picture to prove that this is working.

output_nFIVXG.gif

Run simple! No crazy concatenated HTML strings!

P.S. Sorry, standard SAP’s formatting is lost again. Do not know how to keep it.

BR, Dima

To report this post you need to login first.

6 Comments

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

  1. Andrey Vishnevskiy

    Cool stuff, Dima!

    I just have few suggestions if you please.

    1. I suppose you would like to put last “image” as a gif to provide a quick result look of you work as you did in Asynchronous Saved Search Fetch. Right now it is a jpg file. Could you please correct it?

    2. It’s quite easy to figure out what save_ajax_area method exactly is (just to store bsp element to later retrieve its id, am I right?). But it might be better to provide its code or just to describe it fully in your blog post. If it’s just for the reason to store (tajax area) element id, why don’t you store the id in public controller’s attribute?

    (0) 
      1. Andrey Vishnevskiy

        Hi Dima,

        Great, thank you!

        It’d be good to remove save_ajax_area reference from the text as well ūüôā

        Also I want to share my “lessons learned” (that I’ve noticed during implementation of a table using your solution):

        1. 1 = 1 in the page – in that case ajax call will be performed quiet often (any rendering of the page will cause the call)

             What I did: comment 1 = 1 line in the page and clear gv_config_table and gr_ajax_area (last one – just in case) in DO_CLEANUP_CONTEXT method of view controller class. This also allowed to decrease number of back-end calls and to correctly handle navigation from one object to another similar object. The last one is a scenario when such ajax-table implemented for a table in assignment block of (for example) business partner and you navigate from one to another using Recent Items.

        2. If a corresponding collection will be empty after fill_context_node ( as a result of a search performed or get_related_entities call in there) then “Loading…” text will be still displayed in the table in UI.

             What I did: in IF_CRM_WEB_CALLBACK~HANDLE_REQUEST method before the call of CREATE_TABLE_VIEW_HTML_NEW add a line:

        lr_controller->gr_config_table->emptytabletext = ‘No result found’. “TEXTett.

        to reset emtytabletext back to the original one.

        (0) 
          1. Andrey Vishnevskiy

            No complaints, just my thoughts and lessons. May be it will help someone to figure out what is going on asynchronously ūüôā Thank you for the blog post!

            (0) 
  2. Joost Stallaert

    Hi,

    The solution looks fantastic and I basically got it working. There is however one thing which I cannot make to work: whenever I click on a row (to select it) nothing happens. No roundtrip is triggered, nothing. This issue only occurs when the page is rendered via a callback. When the page is rendered “normally” (through a normal callback, e.g. after clicking on a paging in the table) the row selection does work.

    I have the impression that none of the javascript events are triggered or at least they don’t trigger a roundtrip (row selection, click on header to apply filter, …)

    Does anyone else have experienced this problem?

    Thanks,

    Joost

     

    (0) 

Leave a Reply