Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
VishnAndr
Active Contributor

Preamble

There are regular questions on CRM WebUI space: How to hide the field dynamically on the form? How to modify properties of the field? How to intensify the field? and so on. These questions have different solutions. For instance nithish.pp is writing a series of documents and the first document is about the form. Pretty interesting and certainly worth to read.

I want to share one more possibility. Not so popular and well-known. Google finds only couple hits on it. And the one is the discussion How to display the link dynamically on placing the cursor on a field? I've promised to post a more detailed blog on the topic there and here we go.

The main reason to find this solution was the very interesting blog Developing Content Rich Tool tips in CRM UI using jQuery by ravikiran.chittum. I wanted to bring the content rich tooltip to SAP CRM WebUI configurable page. Everybody knows that the BSP element chtmlb:config is very useful and nice one. But I had no idea how to bring the tooltip through jQuery to such form. There was no appropriate field property available in GET_P method. It seemed that there was no way to do that. But....  :???:

Solution

WebUI folks know that there is such option as iterator available for table BSP elements. And here is the solution! :!:

BSP element chtmbl:config also has such iterator. This possibility was introduced by Note 1460122 - WebCUIF: Programmable adaption of configurable form fields.

The main idea is as follows:

  • you need a class which implements iterator interface IF_CHTMLB_FORM_ITERATOR and its method RENDER_CELL_START.
  • you need to pass its instance to the static method cl_chtmlb_config=>set_iterator right before BSP element chtmlb:config on a view page.

And that is it! :smile:

Use Cases and Examples

Let's take a look on some use cases:

1. Visualization.

Mark the label of the birth date field with red background if the partner is under 18, otherwise mark it with green background. Actually this example is taken from class CL_THTMLB_FORM_IERATOR_SAMPLE which is provided by mentioned note as an example implementation. Here is the part of code how to set iterator in BP_HEAD/AccountDetails view:

<%@page language="abap" %>
<%@extension name="htmlb" prefix="htmlb" %>
<%@extension name="xhtmlb" prefix="xhtmlb" %>
<%@extension name="crm_bsp_ic" prefix="crmic" %>
<%@extension name="bsp" prefix="bsp" %>
<%@extension name="chtmlb" prefix="chtmlb" %>
<%@extension name="thtmlb" prefix="thtmlb" %>
<%
  DATA: lv_xml    TYPE string.
  DATA: lr_iterator TYPE REF TO zl_thtmlb_form_ierator_sample.
  CREATE OBJECT lr_iterator
    EXPORTING iv_context_node = HEADER.
  cl_chtmlb_config=>set_iterator( lr_iterator ).
%>
<chtmlb:config xml         = "<%= lv_xml %>"
    displayMode = "<%= controller->view_group_context->is_view_in_display_mode( controller ). %>"
     mode        = "RUNTIME" />

In fact class ZL_THTMLB_FORM_IERATOR_SAMPLE is a copy of standard sample class CL_THTMLB_FORM_IERATOR_SAMPLE with slight adaptation. The code of the method RENDER_CELL_START is (IF IV_BINDING_STRING is adjusted and div tag used instead of span to enable text-align in style of the label):

METHOD if_chtmlb_form_iterator~render_cell_start.
  DATA: lv_current TYPE REF TO if_bol_bo_property_access.
  DATA: lv_bee     TYPE REF TO cl_bsp_bee_table.
  DATA: lv_label   TYPE REF TO cl_thtmlb_label.
  DATA: lv_date    TYPE d.
  DATA: lv_age     TYPE i.
  DATA: lv_colour  TYPE string.
  IF iv_binding_string = '//HEADER/STRUCT.BIRTHDATE'.
* -> get age from birthdate and mark lable with red background if under 18, otherwise green
    lv_current = gv_context_node->collection_wrapper->get_current( ).
    lv_current->get_property_as_value(
                            EXPORTING
                              iv_attr_name = 'BIRTHDATE'
                            IMPORTING
                              ev_result = lv_date ).
    lv_age = ( sy-datlo - lv_date ) / 365.
    IF lv_age >= 18.
      lv_colour = '#00FF00'.
    ELSE.
      lv_colour = '#FF9999'.
    ENDIF.
* -> create the replacement element
    CREATE OBJECT lv_bee.
    IF iv_element_name   = 'label' .
* -> wrap some colour HTML around the label to make its text green or red
      lv_bee->add_html( html = |<div style="background-color:{ lv_colour };text-align:right">| level = 1 ).
* -> also emphasize the label with standard THTMLB label attribute "design"
      lv_label ?= iv_element_bee.
      lv_label->design = 'EMPHASIZED'.                     "#EC NOTEXT.
    ELSEIF iv_element_name   = 'inputfield'.
      lv_bee->add_html( html = |<div style="border-color:{ lv_colour };border-width:1px;border-style=solid;">| level = 1 ).
    ENDIF.
    lv_bee->add_bee( bee = iv_element_bee  level = 2 ).
    lv_bee->add_html( html = '</div>' level = 1 ).
    ev_replacement_bee = lv_bee.
  ENDIF.
ENDMETHOD.

The result is like this:

You can easily implement interface IF_CHTMLB_FORM_ITERATOR in your view controller class and pass it as iterator to the BSP element. Then you'll be able to use all its advantages (access to context nodes, some utility methods etc.).

2. Hide a field from a view.

It's quite similar to previous one. Even easier. But this method unfortunately leaves the space instead of the field. If someone knows the way how to hide this empty space too - welcome to comment.

The code is:

METHOD if_chtmlb_form_iterator~render_cell_start.
  DATA: lv_current TYPE REF TO if_bol_bo_property_access.
  DATA: lv_bee     TYPE REF TO cl_bsp_bee_table.
  DATA: lv_date    TYPE d.
  DATA: lv_age     TYPE i.
  IF iv_binding_string = '//HEADER/STRUCT.BIRTHDATE'.
* -> get age from birthdate and mark lable with red background if under 18, otherwise green
    lv_current = gv_context_node->collection_wrapper->get_current( ).
    lv_current->get_property_as_value(
                            EXPORTING
                              iv_attr_name = 'BIRTHDATE'
                            IMPORTING
                              ev_result = lv_date ).
    lv_age = ( sy-datlo - lv_date ) / 365.
    IF lv_age < 18.
* -> create the empty replacement element
      CREATE OBJECT lv_bee.
      ev_replacement_bee = lv_bee.
    ENDIF.
  ENDIF.
ENDMETHOD.

The result:

3. Replace the field with other (for instance, custom) BSP element.

Here we come to the main reason of my research. I wanted to bring tooltip looking similar as tooltip in the mentioned blog. Particularly, I'd like to implement a tooltip which would show a customer photo when the user moves the mouse over the ID field. So I created a custom BSP element as a copy of standard BSP element thtmlb:link and enable onMouseOver event and rel attribute in it. After this I was able to achieve the goal! :grin:

Frankly speaking there was also an additional page created to show picture and some coding to get and pass an url of photo attached to this page but this is out of current blog post scope.

The view looks like:

<%@page language="abap" %>
<%@extension name="thtmlb" prefix="thtmlb" %>
<%@extension name="chtmlb" prefix="chtmlb" %>
<%@extension name="bsp" prefix="bsp" %>
<link href="https://blogs.sap.com/sap/bc/bsp/sap/zbp_head/jquery.cluetip.css" rel="stylesheet" type="text/css" />
<script src="/sap/bc/bsp/sap/zbp_head/jquery-1.6.4.min.js" type="text/javascript"></script>
<script src="/sap/bc/bsp/sap/zbp_head/jquery.hoverIntent.js" type="text/javascript"></script>
<script src="/sap/bc/bsp/sap/zbp_head/jquery.cluetip.js" type="text/javascript"></script>
<%
* Form iterator
  cl_chtmlb_config=>set_iterator( controller ).
%>
<head>
<script type="text/javascript">
var $j = jQuery.noConflict();
function LoadPhoto(myElement){
$j(myElement).cluetip({
  cluetipClass: 'jtip',
  width: 1,
  arrows: true,
  attribute: 'rel',
  dropShadow: false,
  hoverIntent: false,
  sticky: true,
  mouseOutClose: true,
  closePosition: 'title',
  showTitle: false,
  topOffset: 85
});
}
</script>
</head>
<chtmlb:config mode = "RUNTIME"
               xml  = "<%= controller->configuration_descr->get_config_data( ) %>" />

The code for rendering the field is:

METHOD if_chtmlb_form_iterator~render_cell_start.
  DATA: zbee_link TYPE REF TO zcl_thtmlb_link,
        lv_photo TYPE string VALUE '/sap/bc/bsp/sap/zbp_head/Photo.htm?param1=',
        lv_photo_url TYPE string.
  IF iv_element_name EQ 'text' AND
     iv_binding_string EQ '//PARTNER/STRUCT.BP_NUMBER'.
    CREATE OBJECT zbee_link.
    zbee_link->id = me->typed_context->partner->IF_BSP_MODEL_BINDING~GET_ATTRIBUTE_NAME( 'STRUCT.BP_NUMBER' ).
    zbee_link->_text   = iv_binding_string.
    zbee_link->onmouseover = 'LoadPhoto(this)'.
    lv_photo_url = me->get_photo_url( ).
    lv_photo_url = cl_http_utility=>if_http_utility~escape_url( lv_photo_url ).
    CONCATENATE lv_photo lv_photo_url INTO lv_photo.
    zbee_link->rel = lv_photo.
    ev_replacement_bee ?= zbee_link.
  ENDIF.
ENDMETHOD.

And the final result:

(Instead of) Conclusion

So with the form iterator we can take great advantages from the tandem of a configurable form and an iterator for modifying the fields. Anyone can try it. And use to achieve the goal. I'll be glad if this post will help someone achieve the result. Thank you for reading this.

11 Comments
Labels in this area