Quantcast
Channel: SAP CRM: Webclient UI - Framework
Viewing all 188 articles
Browse latest View live

Simple Approch to Generate Standardize Buttons

$
0
0

When enhancing a SAP CRM view a few days ago I noticed a simple way to generate standardizes buttons in the Web UI. I'm quite sure that most people know this approach already. Nevertheless, I totally missed it up until know and therefore it would be worthwhile blogging about it.

 

When creating a button I'd usually use one of the following approaches (depending if I need to create the button in a BSP or in ABAP code).

 

<thtmlb:button id      = "SaveandBack"
               onClick = "SaveandBack"
               enabled = "<%= abap_true %>"
               iconSrc = "<%= cl_thtmlb_util=>get_icon_url( 'saveandback.gif' ) %>"
               tooltip = "<%= otr(CRM_IC_COMP_UI_BUAG/SAVEANDBACK) %>" />

 


DATA: button TYPE crmt_thtmlb_button

button-id       = 'SaveandBack'. "#EC NOTEXT
button-on_click = 'SaveAndBack'. "#EC NOTEXT
button-text     = cl_wd_utilities=>get_otr_text_by_alias( 'CRM_IC_COMP_UI_BUAG/SAVEANDBACK' ).
button-tooltip  = cl_wd_utilities=>get_otr_text_by_alias( 'CRM_IC_COMP_UI_BUAG/SAVEANDBACK' ).
button-icon_src = cl_thtmlb_util=>get_icon_url( 'saveandback.gif' ).

 

This approach forces me to do three things which each an every button I create:

  • Search for an appropriate icon
  • Search for or create a suitable icon text
  • Search for or create a suitable tool tip text.

 

As a consequence, all buttons created this way might differ a little bit (e.g. the save icon is used for a button that executes a "save and back" action). This is also true for a large number of SAP standard views in SAP CRM.

 

The solution to this is hidden in the constants of the class CL_THTMLB_UTIL and the type attribute of thtmlb:button. In order to, for example, create a "save and back" button one only needs to look up the correct constant in CL_THTMLB_UTIL. Then this constant can be use to create a button using the code shown below:


<thtmlb:button id   = "SaveandBack"
               type = "<%= cl_thtmlb_util=>gc_icon_saveandback %>"
               enabled = "<%= abap_true %>" />

 


DATA: button TYPE crmt_thtmlb_button

button-id       = 'SaveandBack'. "#EC NOTEXT
button-type     = cl_thtmlb_util=>gc_icon_saveandback.

 

Using the constants defined in the class CL_THTMLB_UTIL it is possibe to create buttons including a icon, a text and a tool tip without the need to search for OTR tests and icons. Furthermore, if the same constants are used for buttons representing the same action, this leads to a nice standardizes UI.

 

If you are interested which icons and texts are created using on of the constants in CL_THTMLB_UTIL you can have a look at CL_THTMLB_UTIL=>GET_ICON_INFO. This method is called in the implementation class of the <thtmlb:button> element (i.e. CL_THTMLB_BUTTON).


How to integrate CRM WebClient UI & NetWeaver Enterprise Portal

$
0
0

Hello everyone,

  

It has been a while since I last published an article on SCN. Creation of a landscape and step by step scenarios require a lot of time and effort, which is often impossible with a full day’s work. This new document covers CRM WebClient UI & NetWeaver Enterprise Portal Integration. Though the concept and the steps are quite simple, it seems that there are gaps that needs addressing. There are three ways that you can integrate CRM & EP; external integration, tight/classic integration and OBN (Object Based Navigation). The examples within are based on CRM Ehp2 and EP 702 and covers the first two scenarios. OBN is beyond the scope of WUI Framework, and hence it is not covered. The document also contains important Notes section, some tips (what is and is not supported) and finally what to consider when opening an OSS incident when you need assistance from SAP. Last but not least, I highly recommend you visiting our WUI Framework WIKI page for other documents which I am sure would be of an interest to you. Happy reading!!!

 

 

Best Regards,

 

Hasan

One breadcrumb issue caused by missing implementation of method GET_MAIN_ENTITY

$
0
0

Issue symptom

We have met with a strange issue in breadcrumb navigation:

 

We first click hyperlink of instance 201400024731

clipboard1.png


And we go to its detail page, then click Inbox Workcenter to return to the search result view. Then we click the second instance 201400024710 to reach its detail page, and click   Inbox Workcenter again. Now we delete the 201400024731 via delete icon in toolbar, however we still can find the entry for it in breadcrumb drop down list. The worse thing is, after we choose the dropdown list for 201400024731, we actually reach the detail page of 201400024710 which is completely wrong.

clipboard2.png

Root cause

We found the issue is caused by missing implementation of GET_MAIN_ENTITY.

clipboard3.png

After implementing it the issue is gone. The reason why that method is necessary is because:

 

 

The class CL_BSP_WD_HIST_MANAGER_BASE has two event handlers:

 

 

ON_ENTITY_DELETED is responsible for the removal of history record of deleted bol instance from history storage.

 

clipboard4.png


it is registered on method ON_HISTORY_TRIGGER,

clipboard5.png

which is the event handler for event:

clipboard6.png

When we are navigating from search result to detail page, GET_MAIN_ENTITY will be called:

clipboard7.png

The returned main entity is registered for event handler ON_ENTITY_DELETED.

clipboard8.png

When this very instance is deleted, the event DELETED is raised and caught by event handler ON_ENTITY_DELETED( see callstack below)

clipboard9.png

The history entry for the deleted bol entity( o:871) is removed in line 32:

clipboard10.png

clipboard11.png

Row one is removed, and in back button drop down list now the entity for deleted bol entity is removed as expected.

Converting HTML to XHTML using CL_HTMLTIDY

$
0
0

For some projects or applications one may need XHTML-data instead of HTML. In some cases you may need XHTML to parse data to Adobe Forms for example.

 

One idea to convert the data is based on the Tidy library, which was originally developed by Dave Reggett (HTML Tidy Project Page)

It's also possible to use this library within the ABAP stack by instrument the class CL_HTMLTIDY.

 

Here I describe roughly the way to do that:

 

1. First you have to convert the HTML to UTF8-XSTRING e.g. with help of the class cl_abap_conv_out_ce or  cl_gstext_tools

Example:

  lv_text_as_xstring = cl_gstext_tools=>convert_string_to_xstring( iv_string  =  lv_html ).

 

2. Create a global obkject  from CL_HTMLTIDY-object: cl_htmltidy=>create( ).

 

3. Set the options for the Tidy-object by using the method set-option from the class. The parameter input encoding has to be 'utf8'

You can also have a look at this german blog: Rüdiger Plantiko: Testbare Oberflächen

 

4. Use the instance (object) of the CL_HTMLTIDY-class to trigger the method to convert. Have a look at the available methods in SE24.

    I will enhance this blog by a step by step manual as soon as possible. Pass the UFT8-XSTRING as Import data.


Unfortunately some tags (e.g. <strong>) are not replaced (e.g. by XHTML-standard <b>). For that you have to use XSLT.

 

 

Regards,

Daniel

Automatic Delta Handling in Webclient UI

$
0
0

A real case which is related to Automatic Delta Handling

I use a ticket which I am struggling with recently to start this blog. It took me almost the whole day to dig out the root cause.

 

How to reproduce the issue - Just create a new Product by clicking new Product button:

clipboard1.png


The strange thing is, after button is clicked, I didn't see the expected new product creation page. Instead, I saw the weird page below: the whole UI area almost kept unchanged except the page tilte changed from "Search:Products" to "Product: New". Why the left product creation page failed to be rendered???


clipboard2.png

How I find the root cause

Since the UI page didn't crash, there is no surprise that I didn't find any related dumps in ST22.

I am 100% sure that there must be some exception occurred in the backend and caught by framework, but unfortunately without any message raised out in UI. So I use the tip described in my blog to start debugging. Several minutes later, I felt really frustrated since the breakpoint for ABAP keyword CATCH is triggered so frequently in UI framework processing. I was completely lost in the debugging. ( At that time I didn't try conditional breakpoint group since I am not sure whether it could help)

 

Then I asked for help from one colleague who is an UI expert. He suggested:" Hey, try to switch off delta handling and try again". Wait, what is the delta handling? After exploring for quite a time I switched it off and retry, here below is the result under delta handling off mode:


clipboard5.png

Bingo! This time the framework did provide quite useful information to me - something wrong in overview page toolbar processing.

 

I looked into GET_BUTTONS method and found there is a case that one initial reference variable is being used.

clipboard6.png

Once that line is executed,

clipboard7.png

The exception is caught by UI framework.

clipboard8.png

Here below is something more I want to share with you regarding Automatic delta handling

 

 

What is Delta Handling mechanism in Webclient UI?

 

The Delta Handling is a collection of mechanisms to reduce the rendering time on the client and the network load when transporting the request and response between server and client. It consists of Manual delta handling ( out of scope of this blog) and Automatic delta handling. The Manual Delta Handling bases on the tag library TAJAX. With this library we can define areas on views and rules for updating these areas basing on events.

 

In most of the case Automatic Delta Handling (ADT) is used. The ADH uses also the technique provided by the tag library TAJAX. Instead of defining complex rules for dependencies between TAJAX-areas, when the page is being prepared for the rendering, ADH detects which areas (e.g. views) of the page have changed. Only such changed areas are then redrawn in the browser. It is nearly transparent for we application developer, as long as there is no too complicated JavaScript used in the UI page. If you are interested with this, you could read the comment on method CL_AJAX_UTILITY->SHOULD_RENDER and debug it.

 

clipboard9.png

Where is ADT mode configured

 

Suppose I log on to UI via business role TPM_PRO, which has DEFAULT as the technical profile:

clipboard10.png

In the SPRO customizing Customer Relationship Management->UI Framework->Technical Role Definition->Define Technical Profile

 

Here we can enable or disable the ADT:

clipboard11.png

How to switch off ADT temporarily

 

TCode: SU3, select "Parameters" TAB, and add the following user parameter "CRM_TAJAX_DH_MODE" and set it to "OFF"

 

clipboard12.png

Make sure you close the browser and open a new one after the change.

 

 

How can I permanently switch off my view for ADH

 

 

All UI component views which are not supported for ADH are centrally maintained in view BSPWDV_ADH_DSBL via SM31:

clipboard13.png

My colleague gave me such suggestion: When you find your UI component works abnormally, it could be helpful to run your UI component with ADT switched off, which sometimes can give you some hint.

Form iterator. Reviewing mistakes.

$
0
0

In my previous blog about form iterator (Form Iterator and How It Should Be Cooked ) I've provided couple use cases. However, since then I've seen some more common requirements on SCN. Which sometimes end with suggestions like 'Build the form completely yourself' or 'Take xml_config and modify it with ABAP' or 'It's not possible'.

My previous blog may confuse someone. It's because 'wrapping' solution (which was taken as an example and not as 'fits-all' solution) doesn't always work. For example, it won't work for input fields in edit mode etc. Due to some reasons unfortunately, I've missed those discussions and caught them too late or participated in them not enough to provide a complete solution.

 

Now I'm trying to correct myself. And here is what I'd like to propose.

Starting from Ehp1 SAP CRM allows defining CSS files easily. Please refer CSS Files and JS Files - User Interface Personalization - SAP Library

IMG entry for this is:

SPRO -> Customer Relationship Management -> UI Framework -> UI Framework Definition -> Skins and Icons -> Define Path for CSS Files.

Please read the help document for this IMG entry before uploading CSS file to MIME repository to make it clear where we need to upload a file depending on a path type used: absolute, relative or local.

 

Why not to take such an opportunity and use it?

Let's assume we create a CSS file with the content:

.zth-greencolor {    background-color: rgb(122, 255, 122); /* green */    border-color: rgb(0, 176, 23);    color: rgb(0, 0, 255); /* blue */
}

Here we define a class with background color, border color and font color.

 

Then following the help topic mentioned above, we upload it to the appropriate place in MIME repository and define it in SPRO.

css file place in MIME repos and settings.png

 

After that, it's good to refresh server cache and local workstation cache.

 

Then we come again into our form iterator defined and set in some WebUI form (which is represented by chtmlb:config element).

Right now we set newly created CSS class for input field.

 

DATA: lr_inputfield TYPE REF TO cl_thtmlb_inputfield.   IF iv_binding_string = '//HEADER/STRUCT.FIRSTNAME'     AND iv_element_name = 'inputfield'.     TRY .         lr_inputfield ?= iv_element_bee.         lr_inputfield->cssclass = 'zth-greencolor'.         ev_replacement_bee ?= lr_inputfield.       CATCH cx_sy_move_cast_error.     ENDTRY.
ENDIF.

And we can see the result.

screenshot result1.png

 

Additionally we can define other entries in our CSS file to meet some special requirements.

 

/* works for non-mandatory input fields or error-free mandatory input fields */
.zth-greencolor {    background-color: rgb(122, 255, 122); /* green */    border-color: rgb(0, 176, 23);    color: rgb(0, 0, 255); /* blue */
}
/* works only for mandatory input fields with errors */
.th-onerror .th-if.zth-yellowcolor {    background-color: rgb(255, 255, 122) !important; /* yellow */    border-color: rgb(0, 176, 23) !important;    color: rgb(0, 0, 255) !important;
}
/* with and without error in mandatory inputfields */
.th-if.zth-pinkcolor {    background-color: rgb(255, 122, 255) !important; /* pink */    border-color: rgb(0, 176, 23) !important;    color: rgb(0, 0, 255) !important;
}
/* enlarge label and text view */
.zth-lb-enlarge {    font-size: 24px;
}

The result:

tripple result.png

 

Luckily, SAP provides 'cssclass' attribute for input field tag (thtmlb:inputfield). But it's missed in such elements as labels (thtmlb:label) and text views (thtmlb:textview). The last one represents input fields in view mode. In standard, we can influence the style of these tags only using ‘design’ attribute. Which is then converted to certain CSS classes. There is also 'size' attribute available for text view tag. But I didn't manage to find any footprints that it's handled in the tag. Certainly, we can use 'wrapping' mechanism in this case. But there are some restrictions. Because of the fact that BSP elements may actually be represented as a couple of nested html tags. For example increasing font size with wrapping mechanism works only for text views (e.g. input fields in view mode) and doesn't work for labels. Therefore, I personally prefer the same approach as for input field described above. The solution is to create two z-BSP elements, which are enhanced with the appropriate functionality.

 

The steps for this are below:

We need to have already created BSP extension. Let's say ZZTHTMLB (we create it in se80 and provide ZZTHTMLB as a name and as a default prefix here; give the Short text as you like).

Then we go to BSP extension THTMLB and copy 'label' BSP element into our own BSP extension (keeping the name of the tag the same). Activate everything (I assume below that you know when you need to save and activate your work, so I will not repeat it each time).

We receive such a tag.

screenshot tag1.png

 

Go to Attributes tab and add a new attribute:

screenshot attribute zcssclass.png

 

Then in se24 create a new element handler class. I choose ZCL_ZZTHTMLB_LABEL as a name. It's a simple class, which inherited from CL_THTMLB_LABEL.

Add an attribute:

screenshot class attribute zcssclass.png

 

Then redefine IF_BSP_ELEMENT~DO_AT_BEGINNING method and adjust it with the following statement (in my current system Ehp2 SP9 it's a line number 107)

 

  IF me->mc_accessibility IS INITIAL AND me->wrapping IS INITIAL.    CONCATENATE out_string ' th-ellipsis'    INTO out_string.  ENDIF.
* Z-enhancement: add css style if provided  IF me->zzcssclass IS NOT INITIAL.    DATA lv_cssclass TYPE string.    lv_cssclass = cl_thtmlb_util=>escape_xss_xml_html( me->zzcssclass ).    CONCATENATE out_string lv_cssclass INTO out_string SEPARATED BY space.  ENDIF.
* end of Z-enhancement  IF me->width IS NOT INITIAL OR me->wrapping IS INITIAL.

Change element handler class in ZZTHTMLB:label tag to this newly created class.

screenshot tag2.png

 

We can do the same for text view. It's obvious that it should be a different element handler class (inherited from CL_THTMLB_TEXTVIEW). The only difference is that you need to concatenate your CSS class into html variable instead of out_string.

 

  IF me->wrapping IS INITIAL.    CONCATENATE html ` th-tx-nowrap` INTO html.  ENDIF.
* Z-enhancement: add css style if provided  IF me->zzcssclass IS NOT INITIAL.    DATA lv_cssclass TYPE string.    lv_cssclass = cl_thtmlb_util=>escape_xss_xml_html( me->zzcssclass ).    CONCATENATE html lv_cssclass INTO html SEPARATED BY space.  ENDIF.
* end of Z-enhancement  CONCATENATE html `" ` INTO html.
* Taking care of the WIDTH parameter through inline styling:  IF me->width IS NOT INITIAL.

 

Now we're ready. Let's go to our form iterator and put the below coding for appropriate fields.

 

DATA: lr_label TYPE REF TO cl_thtmlb_label,         lr_zlabel TYPE REF TO zcl_zzthtmlb_label,         lr_textview TYPE REF TO cl_thtmlb_textview,         lr_ztextview TYPE REF TO zcl_zzthtmlb_textview.   IF iv_binding_string = '//HEADER/STRUCT.FIRSTNAME'     OR iv_binding_string = '//HEADER/STRUCT.LASTNAME'.     IF iv_element_name EQ 'label'.       TRY .           lr_label ?= iv_element_bee.           lr_zlabel = zclg_zzthtmlb_label=>factory(               design        = lr_label->design               encode        = lr_label->encode               for           = lr_label->for               id            = lr_label->id               labeltype     = lr_label->labeltype               required      = lr_label->required               switchid      = lr_label->switchid               text          = lr_label->text               textdirection = lr_label->textdirection               tooltip       = lr_label->tooltip               width         = lr_label->width               wrapping      = lr_label->wrapping               _text         = lr_label->_text ).           lr_zlabel->zzcssclass = 'zth-lb-enlarge'.           ev_replacement_bee = lr_zlabel.         CATCH cx_sy_move_cast_error.       ENDTRY.     ELSEIF iv_element_name = 'inputfield'.       TRY .           lr_textview ?= iv_element_bee.           lr_ztextview = zclg_zzthtmlb_textview=>factory(             align         = lr_textview->align             design        = lr_textview->design             encode        = lr_textview->encode             id            = lr_textview->id             layout        = lr_textview->layout             size          = lr_textview->size             switchid      = lr_textview->switchid             text          = lr_textview->text             textdirection = lr_textview->textdirection             tooltip       = lr_textview->tooltip             type          = lr_textview->type             width         = lr_textview->width             wrapping      = lr_textview->wrapping             _text         = lr_textview->_text             _tooltip      = lr_textview->_tooltip             _type         = lr_textview->_type ).           lr_ztextview->zzcssclass = 'zth-lb-enlarge'.           ev_replacement_bee = lr_ztextview.         CATCH cx_sy_move_cast_error.       ENDTRY.     ENDIF.
ENDIF.

And here is the result:

 

screenshot result2.png

 

Hope this will help SCN members satisfy their requirements. Do not stop exploring for good!

 

Reference materials:

CSS Files and JS Files - User Interface Personalization - SAP Library

CSS Tutorial on W3Schools

Almost Everything About Transaction Launcher - Part II

$
0
0

Dear colleagues,

 

Part II of Almost Everything About Transaction Launcher is now published. Sorry it took me forever to get to this one. Things have been quite busy. Since you are already experts in configuration and troubleshooting TL, I decided to change the format. This one focuses on some interesting issues that I have come across on the topic. It may look like an FAQ, but to call it one would be an injustice . The document also includes an interesting Notes/KBA section as well as things to consider when you are opening an OSS incident seeking SAP’s assistance. The link to the document is also published on our SCN's WebClient UI Framework WIKI page. I would really appreciate your feedback on the article - things that were helpful and things I missed. Enjoy!!!

 

 

Warm regards,

 

 

Hasan

How to implement a simple character counter

$
0
0


In the blog we talk about the social media integration into CRM Interaction center agent inbox, which allows end users to directly reply facebook posts & tweets in CRM system. In order to achieve this we implement a very simple character counter which has similar functionality as that in twitter website:


clipboard1.png

The counter described in this blog is delivered by SAP in CRM 7.0 EHP3. You can find it in UI component SMCOV, view ReplyMessageView.htm. Its function is slightly different from twitter: it does not display the left number of characters which is allowed to input, but the number of characters which are ALREADY typed by end user.

 

 

The following functionalities are supported by this simple counter:

 

1. Whenever you add, delete or change your input in text area, the number of characters you have typed will be automatically updated below the text area

2. The cut & paste event are also captured by the counter

 

Any other advanced functionalities like url automatically highlighted as hyperlink is not supported by this simple counter.


clipboard2.png

Here below is the implementation of this counter:

 

1. In your UI component view, draw the visual area of the counter which will show the text "The number of characters entered:XXX" via html p tag:

 

<p id="COUNTER_TXT"  style="margin-left: 8px; margin-top: 1px; margin-bottom: 4px; margin-right: 8px; color:rgb(102,102,102)"></p>

 

2. in line 32, the function handleClick acts as the event handler which will be called automatically whenever the content in the text area is changed.

 

In line 34 the final text in the visual area of the counter is populated.

For translation purpose, the text is not hardcoded but stored and got in Online Text Repository:

 

 

lv_title_prefix = cl_wd_utilities=>get_otr_text_by_alias( 'CRM_UIU_SOC_SMC/COUNTER_TXT' ). "#EC NOTEXT.

 

lv_title_prefix = lv_title_prefix && ':'.

 

In line 35 the current number of characters is updated in the visual area of the counter. The variable counter is a DOM variable which represents the html tag p with ID COUNTER_TXT, which is retrieved later.

clipboard3.png

 

The function fillTitle is designed to ensure the counter still displays the correct number of typed characters in text area when the UI is rendered for the first time ( at that time no event for the text area will be fired ).

 

Here the biggest challenge is how to get the ID of the text area, so that we can use document.getElementByID to get its DOM node and then get the actual content which has been typed in the text area.

 

As this text area is not manually created via native HTML code, it is impossible to get its ID directly in the view.

 

clipboard4.png

However, we could investigate on the naming convention of this ID via development tool ( just clikc F12 on web page) of IE.

 

Click Find->Select element by click, then click on the text area, and development tool will automatically locate the native html textarea element, and then we can observe that the naming convention for it is <component_id>_socialpost_struct.content.

clipboard5.png


The current component id is available in the attribute component id of view controller, so finally we can populate the ID of text area via the following code:

clipboard6.png

3. The left code is very easy to understand: retrieve the DOM node for input textarea ( line 47) and visual area of counter( line 48), and register the event handler for three events on text area element.

clipboard7.png


Dynamic fields in WebUI using GET_A method (no new configuration needed)

$
0
0

Hi community,

 

 

 

Yesterday i've found a nice way to show/hide fields dynamically in WebUI!!

 

 

The first idea that occurred to me was to create 2 different configurations, one with the field and the other without... Then go to method DO_CONFIG_DETERMINATION and select the correct configuration according to the logic that i wanted...

 

For me, this is not the right approach! WHY? imagine a requirement where we have 10 dynamic fields:

 

 

For 1 dynamic field, we need 2 configurations;

For 2 dynamic fields, we need 4 configurations;

...

 

 

 

I've tryed to find a new solution using different foruns and blogs but unsucessfully... and then i've found the light (:P)

 

 

 

 

My solution is based on the creation of a custom Switch and Business Function, and used them in the BSP application (using method GET_A to change the visibility). Please check the following example:

 

 

 

 

 

Go to transaction BSP_WD_CMPWB, open Component SRQM_INCIDENT_H and view IncidentHeaderEF.

Let's assume that we want to show/hide field "status" (LCSTATUS) from context node BTADMINH.

 

 

Note: All the objects should be enhanced!

 

 

srqm_incident_h.png

 

 

 

The objective is to hide field LCSTATUS:

WebUI_ServReq.png

 

 

 

 

Now i will describe the steps to hide the field:

  • Create Switch using SFW1:

SFW1.png

  • Create Business Function using SFW2:

SFW2.png

  • Create Business Function Set using SFW3:

SFW3.png

  • Activate Business Function in SFW5
  • Go to SM30 and open CRMV_GIL_COMP_AT:

bol_attribute.png

  • In this view, we will set the attributes from BOL Objects with a switch ID and visible or not (check on GENIL_MODEL_BROWSER):

GENIL_MODEL_BROWSER.png

  • Now the BOL attribute has a switch ID. Next step is to maintain the visibility in the view of the component. This should be done in method GET_A of the attribute (in this case LCSTATUS):

get_a.png

  • If we open the WebUI, the field status should be hidden:

invisible.png

 

 

 

IMPORTANT NOTE: this will not work for extensions in AET!!! the standard will not go through GET_A of the attribute.

The reason why is because the name of the attribute starts with "EXT."...

To solve that a new method should be created in the class of the context node:

Untitled.png

Untitled.png

 

 

 

Hope this can solve some problems that both have in SAP CRM

How to deal with error message raised from UI component workbench

$
0
0

In this blog I will demonstrate how I resolve the error message "endless binding loop" raised by UI workbench. I would not emphasize the issue itself, but would rather share with you how I would deal with such error messages raised by UI workbench in my daily life.

 

 

The issue is we have the context node PARAMS defined in component controller, which is bound to node with same name defined in view LogView02.

 

However, the node in view LogView02 is again set to be bound to the node in component controller by mistake, leading to an endless binding loop ( A is bound to B and B is also bound to A ). So the error message is raised by workbench. I planned to use the context menu item "Delete binding" to delete the binding from component controller node to view controller node, but there is no such context menu item available on the errorous context node.

 

 

So I go through the following trouble shooting process:

clipboard1.png

1. find where the error message is raised by workbench

 

 

This is quite easy, just click on the red icon of the error message, and we get required information on the technical help: message class id BSP_WD_TOOLS, message number 082.

clipboard2.png


Go to tcode SE91, use where used list on that message, only one hit in below method.

clipboard3.png

2. figure out why the error message is raised

 

Set a breakpoint on the method found in step1, go to UI component workbench and double click on component controller again, breakpoint is triggered.

Now we get to know the error is caused by the failed internal table insertion done in line 12.

clipboard4.png


The insertion failed because a duplicate record is tried to be inserted to the internal table while the record with the same key( cnode_name and cnode_class ) already existed there. This duplicate record just represents the wrong data binding from component controller context node to view controller context node, which is what we expect to delete.

clipboard5.png

3. figure out why the duplicate record is created

 

It is expected that the duplicate record in step 2 should never be created, so it is necessary to find out where it is being created. We have to go to the outer callstack of the record insertion, that is callstack layer 22. Now we know the generation of the duplicate record is caused by the evaluation of variable lv_target_controller_class in line 83.

clipboard6.png

4. figure out why the binding target controller class is not initial

 

from the method get_cnode_type in step3, we know the lv_target_controller_class is filled by CL_BSP_WD_APPL_MODEL~GET_CNODE_TYPE.

We are now quite near to the issue root cause: if we find out how the UI workbench determines the binding relationship, we should then know how such relationship is maintained or determined. Based on the finding we will finally know how to delete the wrong relatinship.

 

Set a breakpoint on the method and restart the workbench again and navigate to component controller:

clipboard7.png


Now workbench is loading the source code of method CREATE_PARAMS of component controller context node PARAMS's implementation class and stored it into internal table LT_SOURCE.

clipboard8.png

Have you noticed the hard coded string 'DO_CONTEXT_NODE_BINDING' in line 46?

clipboard9.png

5. figure out where and how binding relationship is maintained by UI workbench

 

Final finding: everytime we define a context node binding, UI workbench will automatically generate the following code ( starting with owner->do_context_node_binding )in method CREATE_<context node name>. When UI workbench is displaying the context node, it will locate that hard coded string and get the necessary information by parsing the source code ( via ABAP keyword SCAN ABAP-SOURCE ).

clipboard10.png

clipboard11.png

after we delete the automatically generated code for wrong binding on context node ( line 16 ~ 23 ) in method CREATE_PARAMS, the endless binding loop is resolved.

 

Summary

 

my favourite way to deal with message raised by UI workbench:

 

find out where the message is raised -> find out why the message is raised -> find out the wrong setting / development object which leads to the message

-> correct the mistake.

Refresh Button in IC Web Client

$
0
0

Introduction

In SAP CRM 7.0 the BOL and GenIL do a very good job related to data caching. This caching is necessary to allow for a good performance in the Web UI as the need for actually fetching data from the data base is reduced. However, sometime this data caching also leads to some problem.

 

In the SAP CRM 7.0 for Utilties implementation for one of our clients we implemented a quite advanced account overview screen in the IC Web Client. The call center agents mainly work in the account overview and start the necessary processes using context menus (see the screen shot below). Due to the caching of the BOL we sometimes have the situation, that the data in the account overview isn't refreshed after some process has been performed. This is especially true for the view processes were SAP IS-U transactions are called via the transaction launcher (cf. Almost Everything About Transaction Launcher - Part I and Almost Everything About Transaction Launcher - Part II). The result is, that the call center agents get confused and start to double check if they did something wrong or if it is one of the caching issues. This double checking is usually performed by ending an interaction and identifying the account again.

 

Due to this issues, the agents regularly asked for a refresh function in the account overview screen. So finally I set down an implemented this functionality.

 

Implementing a Refresh Button for the Account Overview

In order to provide the request refresh functionality I enhanced the component IUBOTREE with a small refresh button (see screen shot below).

2014-02-28 17_49_24-Interaction Center - [Übersicht für Andreas Müller] - Internet Explorer bereitge.png

In order to implement the refresh functionality the following steps were necessary.

 

Step 1: Enhance the view IUBOTREE/IsuBolTree

2014-02-28 18_07_48-CVQ(1)_100 Structure of Component IUBOTREE - Enhancement Set ZES_CRM.png

 

Step 2: Add the refresh button to the BOL tree.

In order to add the refresh button to the view I overwrote (I never can get used to the SAP terminology of "redefine") the method GET_ACTIONS  in the view controller (ZL_CRM_IU_COL_TREE_IMPL with the following code:

 

METHOD get_actions.   DATA: action     TYPE crmt_thtmlb_button,         window     TYPE REF TO cl_bsp_wd_window,         usage_name TYPE string.   result = super->get_actions( mode = mode ).   window = me->view_manager->get_window_controller( ).   usage_name = window->get_component_usage_name( ).   IF usage_name = 'usageIUBOTREE_2'.     action-id       = 'refresh_tree'.     action-on_click = 'refresh_tree'.     action-enabled = abap_true.     action-type = cl_thtmlb_util=>gc_icon_refresh.     APPEND action TO result.   ENDIF.
 ENDMETHOD.


Step 3: Implement the event handler EH_ONREFRESH_TREE.

In order to refresh the data I simply performed a reset of the BOL, closed the oen RFC connections to the SAP IS-U and navigated back to the account overview. This way all the data in the account overview is refreshed without the need to end the interaction an identify the account again. The call center agents love it.

There is one caveat to this approach. Any open changes that haven't been committed yet, will get lost during the BOL reset.

 

METHOD eh_onrefresh_tree.   DATA: rfc_dest    TYPE bdbapidst,         bol_core    TYPE REF TO cl_crm_bol_core,         nav_service TYPE REF TO  if_crm_ui_navigation_service.   "reset the BOL   bol_core = cl_crm_bol_core=>get_instance( ).   bol_core->reset( ).   "reset all RFCs to IS-U   zc_crm_cl_cxx_tools=>get_rfc_destination( EXPORTING iv_dialog      = abap_false                                             IMPORTING ev_destination = rfc_dest ).   CALL FUNCTION 'RFC_CONNECTION_CLOSE'     EXPORTING       destination = rfc_dest     EXCEPTIONS       OTHERS      = 1.   "navigate back to the overview page   nav_service = cl_crm_ui_navigation_service=>get_instance( ).   IF nav_service IS BOUND.     nav_service->navigate( iv_link_id = 'UTL-OVW-WC' ).   ENDIF.
 ENDMETHOD.

Timeout page and WebUI freezing issue - Another cause

$
0
0


Sometimes you would see the following page if you are clicking anywhere in a page which is idle for quite a long time.

clipboard1.png

However, there are definitely some other causes which would also lead to this timeout page - the session itself is not timeout, instead within the session, there are some exceptions raised in the backend and caught by the UI framework. As a result you could not see any dumps in ST22, and this timeout page would sometimes lead you to the wrong way of trouble shooting. For example in this thread, some friend is suggesting to enlarge the related timeout profile in RZ10. For sure that would definitely not work, since the issue in the thread is nothing to do with the real timeout issue, but instead the exception caused by a custom enhancement.

 

I would share with you my example how to find the root cause of this kind of I call it "pseudo" time out issue in an efficient way:

 

My example

 

click the Service Order ID for the first time, nothing happended. Click it again( or any other clickable part in the UI), I get the above timeout page.

clipboard2.png

How to figure out the root cause

 

 

I have two different approaches. The first one will take several minutes to find the root cause via debugging.

 

1.  Create a breakpoint based on exception class CX_ROOT( for detail see this blog)

clipboard3.png


Launch UI and click hyperlink for the first time, the breakpoint is triggered and debugger stopped. In the status bar we get the hint that exception CX_BSP_WD_EXC_WRAPPER occurs. Set another breakpoint in its CONSTRUCTOR method.

clipboard4.png

2. Relaunch the UI, the breakpoint in exception class CONSTRUCTOR is triggered, telling us there is something wrong with a custom UI component ZCUSTOM/MainWindow. In line 51 we know the exception class CX_BSP_WD_INCORRECT_IMPLEMENT. Set the breakpoint in its CONSTRUCTOR again.

clipboard5.png

3. Relaunch the UI, now we find root cause: The overview page tries to display the view defined in ZCUSTOM/MainWindow, however it is not in the parsed component usage repository table ( me->usages in line 4)

clipboard6.png

Double check it in UI workbench it is because the custom UI component is added as component usage based on enhancement set A, however currently enhancement set B is active in current client.

clipboard7.png

The second approach is even more efficient. You could enable the UI framework to persist the exception which are raised and caught somewhere for example your own Z table with little effort so that it is convenient for you to check them afterwards.


In my example, I could immediately know this issue is caused by incorrect component usage with the exact usage name without debugging.

clipboard8.png

A small component repository parse tool and its usage

$
0
0

I use the issue in this blog to demonstrate the usage of this small repository parse tool:

 

 

We need to know under which enhancement set the component usage "ZCUSTOM" is added to UI component BT116H_SRVO.

clipboard1.png


This customizing activity could allow us to compare the runtime repositry between the original UI component and the enhanced one:

clipboard2.png

However, if there are too many enhancement sets in the system, it could be very inefficient for manual comparison.

Fortunately the comparison could be done by code below.

 

The report is quite simple:

 

 

1. in line 9, get all enhancement sets list under which the UI component is enhanced.

 

 

2. get the enhanced BSP application name and page name in line 11 and 12, then get the component usage information for each enhanced BSP application via repository tool, then filter it by usage name "ZCUSTOM".

 

REPORT zbsp.
CONSTANTS: cv_host TYPE o2applname VALUE 'BT116H_SRVO'.
DATA: lt_enh_sets TYPE bsp_dlct_ehset,      ls_enh_set LIKE LINE OF lt_enh_sets,      lt_extension TYPE STANDARD TABLE OF bspwd_comp_ext,      ls_extension LIKE LINE OF lt_extension,      lt_usages TYPE bsp_wd_cmp_usage_descr_tab,      ls_usage LIKE LINE OF lt_usages.
lt_enh_sets = cl_bsp_dlc_config_util=>get_eh_sets_of_comp( iv_comp_name = cv_host ).
CHECK lt_enh_sets IS NOT INITIAL.
SELECT * INTO TABLE lt_extension FROM bspwd_comp_ext FOR ALL ENTRIES IN lt_enh_sets WHERE   enhancement_set = lt_enh_sets-enhancement_set AND comp_name = cv_host.
LOOP AT lt_enh_sets INTO ls_enh_set.  READ TABLE lt_extension INTO ls_extension WITH KEY enhancement_set = ls_enh_set-enhancement_set comp_name = cv_host.  IF sy-subrc = 0.    CLEAR: lt_usages.    CALL METHOD zcl_view_repo_tool=>get_repo_metadata(      EXPORTING        iv_comp_name = ls_extension-bsp_appl        iv_page_name = ls_extension-rt_rep_page      IMPORTING        et_usages    = lt_usages ).    READ TABLE lt_usages WITH KEY usage_name = 'ZCUSTOM' INTO ls_usage.    IF sy-subrc = 0.      WRITE: / 'EnhancementSet: ', ls_enh_set-enhancement_set,      ' defines component usage to component: ', ls_usage-child_cmp_type.    ENDIF.  ENDIF.
ENDLOOP.

The small parse tool zcl_view_repo_tool just parse the repository xml from database table and convert it to two internal tables which contains the view information and component usage information. Its source code could be found in attachment.


We can compare the report execution result and the manual check via customizing activity: they are exactly the same.

clipboard3.png

clipboard4.png

clipboard5.png


UI Configuration determination logic introduction

$
0
0

This blog will try to introduce the Webclient UI Configuration determination logic to those friends who are new for this topic.

 

Suppose I log on Webclient UI via Business role SALESPRO and have opened Sales Order overview page and F2 to open technical information page, what are the meaing of the left four fields ( Searched For) and the right four fields ( <DEFAULT>) ?

clipboard1.png

 

 

                                                 Figure1 Technical information page

 

In UI workbench, there are 8 standard configuration pre-delivered by SAP and 1 configuration done by customer.

clipboard2.png

                                   Figure2 View configuration list for Sales Order detail view

 

The SAP configuration data is storaged in table BSP_DL_XMLSTRX2 while customer configuration in BSPC_DL_XMLSTRX2.

 

The configuration determination logic could be summarized as the following:

 

1. The four fields config key, component usage, object type and object subtype are evaluated by framework to determine which configuration should be loaded. The priorities of these four fields are different and hard coded by SAP, see followng picture. These 22 table rows are called "Configuration Access sequence".

 

2. Customer configuration precedes SAP configuration. If a customer configuration is evaluated and accepted, the framework will stop the determination process and load it.

clipboard3.png

                                            

 

 

                                                       Figure3 Access sequnce table

 

Briefly speaking, the configuration determination logic could be concluded as below process:

 

1. framework will build the access sequence table gt_access_sequence, which has 22 entries as listed in figure3.

2. framework will load the 8 sap configuration information( config key, component usage, object type and object subtype ) to internal table it_config_sap

and 1 customer configuration to it_config_cus.

3. LOOP AT gt_access_sequence, within each loop, check it_config_cus whether there are matched configuration. If found, mark it as "Found" configuration and stop the process. If not found ( ie, the 11 times LOOP finish ), the framework will LOOP AT gt_access_sequence again from beginning, but this time the table it_config_sap is checked instead.

 

Let's use the SalesOrder detail view as example to make this process more clear:

 

1. Framework will try to load a configuration which matches the four fields displayed in debugger. These four fields are just considered as "Searched for" fields shown in figure 1.

clipboard5.png

                                                                                Figure4 search key

 

2. load the SAP and customer configuration data:

clipboard6.png

The internal table looks exactly the same as what we see in UI workbench ( Figure 2 ):

clipboard7.png

3. if the determination is being executed in a customer system, there are totally 22 ( 11 for customer configuration and 11 for SAP configuration ) loop until a match is found.

clipboard8.png

the gt_access_sequence is filled according to Figure3.

clipboard9.png

For each fields, X means the corresponding field in it_config_cus or it_config_sap is checked with the search key passed in ( figure4 ),

                      space means <DEFAULT>.

clipboard10.png

 

clipboard11.png

clipboard12.png

All 11 times LOOP for it_config_cus failed, so it_config_sap is now evaluated.

The matched one is finally found in the last attempt, and since it belongs to SAP configuration, so in figure1 "Standard Configuration" is marked for Configuration Origin.

 

clipboard13.png

clipboard14.png

UI Text label determination logic

$
0
0

In this blog we have discussed the logic how the correct UI view configuration is chosen by framework in the runtime.

 

You may have observed that for each field, there is the attribute "Label Origin", which indicates where the label text comes from.

 

clipboard1.png

There are three types of text origin and their determination priority are sorted in the descending order:

 

1. Text Repository

2. Design layer

3. ABAP Dictionary

 

See  an example:

 

I just create a simple component with component set PROD_ALL loaded, and add two fields from Genil Model node Product: PRODUCT_ID and OBJECT_FAMILY_DESC.

 

For PRODUCT_ID, I don't change its label so its Label Origin is "Data Dictionary".

clipboard2.png

for the latter, I change the default one to "Description 1", so the origin changes to "Text Repository", since it has higher priority.

clipboard3.png

If I assign the context node to the Design layer object PRD_MATSRV as below,

clipboard4.png

and make some changes on the design object entity:

clipboard5.png

the origin for PRODUCT_ID changes to "Design layer", since it has higher priority than "ABAP Dictionary".

 

To debug the label determination logic yourself, you can set BP in method below. The logic is the same as UI configuration determination logic - customer stuff always precedes SAP stuff.

 

clipboard7.png

or use transaction code WCF_FA to get field origin overview of a given UI component:

clipboard8.png


Webclient UI Switch related processing

$
0
0

Do you know the meaning of these two checkboxes in F2 popup?

clipboard1.png

Let's first learn some prerequisite knowledge:

 

 

In Webclient UI workbench the poweful functionality is provided to ensure that the given feature is only available, if the bound business switch is in active status. For example you can open component BP_HEAD and find many view are added to overview area with a related business switch.

clipboard2.png

The same logic for navigation link and component usage:

clipboard3.png

clipboard4.png

in this blog we have discussed the ui configuration logic and know the customer configuration precedes the sap configuration. After the correct configuration is determined and IF it is sap configuration, framework will load the configuration xml data with the logic below:

 

 

1. if pre_proc_active_config_s is X ( we will discuss how this flag is initialized later )

 

framework will first try to load configuration data from table BSP_DL_XMLST_PR( Processed Standard Configuration for switch related handling ), if nothing found, then try BSP_DL_XMLSTRX2 instead ( Storagetable for delivered XML layout descriptions ).

 

For customer configuration, the configuration data is always loaded from table BSP_DL_XMLSTRX2.

clipboard6.png


In order to verify the described process above, I create a simple component with one overview page which contains only one assignment block which are bound to a business switch. The switch is set as deactivated.

clipboard7.png

Then I launch the UI. Since it is the first time the UI is accessed, it is apprarently that no entry for ZSWITCH in table BSP_DL_XMLST_PR,

so data is fetched from BSP_DL_XMLSTRX2 instead. BSP_DL_XMLSTRX2 stores configuration data which does not take switch handling into consideration.

After that, framework will try switch handling centrally in method DO_SWITCH_REL_HANDLING_RT:

clipboard8.png


In this method, you can find the processor for each type of switch related handling. In my example ( overview page) it is CL_BSP_DLC_LIST_BASED:

clipboard9.png

The switch handling is done by the processor method PROCESS_CONFIG_XML:

clipboard10.png

The assignment block view is considered as inactive due to the deactivated switch, however it is put to , so the ev_changed is set to X ( the checkbox Changed by Switch processing in F2 )

clipboard11.png

Finally the switch processing result is persisted to table BSP_DL_XMLSTRX2. So when the UI is reopened next time, the stored entry will be fetched instead.

clipboard12.png

When is pre_proc_active_config_s set to X

 

it is controlled by CL_BSP_DLC_CONFIGURATION2=>SWITCH_PROC_ACTIVE_CONFIG_S but could be deactivated via user parameter BSP_DLC_SWITCH_PROC.

clipboard13.png

CL_BSP_DLC_CONFIGURATION2=>SWITCH_PROC_ACTIVE_CONFIG_S will by default only be set to X if current system is set up as customer system.

clipboard14.png

You could also set value  VDTVRT to the user parameter, then UI framework will raise a notification message for you once the switch related handling is detected: 

clipboard15.png

clipboard16.png

The corresponding logic could be found in method below:

clipboard17.png

SAP CRM: Webclient UI - useful commands like F2

$
0
0

All of us who work as SAP CRM consultant knows what’s behind the F2-button(Key) when using the  SAP CRM Webclient UI. For others, it triggers the launch of a popup with all technical information about the current layout at run time. This is very useful information which can be used to determine which components are used and (current) configurations that are called.


However, there are many more shortcuts are available in the Web UI that are not so familiar/popular and I will lists them in this blog.


In order to know which are commands/shortcuts that can be used in the Web UI, you have to click  the CTRL + ALT + SHIFT + F2 keys on your computer keyboard simultaneously. This will give you all the options you have:

 

F2 -SS1.png

F2 : Technical data:  For anyone doing configuration in SAP CRM, all the information in below screen show like UI Component, View Context now, attribute..etc is useful.

 

F2 -SS2.png
F2 + ALT : Conditional breakpoints

 

F2 -SS3.png

For more information, like how to set these type of breakpoints go to How to Debug CRM Webclient UI blog and debugging UI.

 

F7 + CTRL + SHIFT: Performance tracker

F2 -SS4.png

 

This little helper is very useful if you want to see what impact an action executed in the Web UI has on the performance.

  1. Create Memory Snapshot: It has the same functionality as a memory snapshot in S_MEMORY_INSPECTOR.

   2.  Start Backend Runtime Analysis: It creates a run time trace that can be read via transaction SAT.

 

ALT + CTRL+F2 : System information

F2 -SS5.png


This information was only visible from the SAP GUI by clicking System=>Status in old version, so it can save your time by using this shortcut directly in the Web UI. It’s very useful when searching for sap notes, raising OSS etc.

 

ALT + SHIFT+F2: View Hierarchy

F2 -SS6.png

 

This popup is useful to see how the views and components are linked together in a hierarchy. Also,  You can double click to see the properties per component (Technical details), without going to the SAPGUI and into BSP_WD_CMPWB transaction.


Reference :

SAP CRM: There&amp;#8217;s more than just the F2 in the WebUI.. .

How to Debug CRM Webclient UI

$
0
0

In this blog, I'd like to explain ways of debugging CRM Webclient UI. As you are that there are several ways to start debugging the CRM webclient.

1. Setting a external breakpoint in the code(i.e. in a BADI or in the BSP Workbench)

2. Conditional Breakpoints:

 

 

1. Setting Breakpoints in the code

If you know what code you want to debug, of course you can easily set a breakpoints(External) in the coding, and when calling a screen in the web client (or clicking a button or whatever), the debugger will automatically pop up.

 

Note:-In Web UI, only external breakpoints will be considered from the web client (Refer SAP Help).

 

 

If you do not know exactly where a problem is occurring, you can also try running a SQL trace using transaction ST05 or new tcode SAT . In the trace, doubleclick on the line you are interested in in the column containing the operation (like OPEN, PREPARE or FETCH). This will open the ABAP statement where the database call was made. You can now set a breakpoint here. Running again will pop up the debugger.

 

2. Conditional breakpoints.

The use of conditional breakpoints can be activated using transaction SAAB.

F2 -SS7.png

In SAAB, enter checkpoint group CRMUIF_CONDITIONAL_BREAKPOINTS, and click the activate button.

F2 -SS8.png

In the personal activation box, tick the ‘BREAK' radio button under ‘Assertions’ and Save.

 

You can also Set conditional breakpoints directly from web client UI using Alt+F2 command. This will open the following window:

 

F2 -SS3.png

Below are useful conditional breakpoints which will be useful:

 

(a) UI Framework – Common Application Features -> Navigation via Navigation Bar or Cross Component. : This will break on every screen change.

(b) UI Framework -> Create Text Message : This will break when a message is raised.

(c) UI Framework ->  View Controller - Handle Event (*) : This will break when an event is raised.

(d) UI Framework -> View Controller – Do Prepare Output :This will break on the do_prepare_output (the generation of a screen).

(e) Generic Interaction Layer -> GenIL Component – Get Query Result :This will break before a GenIL query is called.

 

Reference -

How to debug CRM Webclient

Debug Webclient UI

Debug Webclient.

CRM_IC WebClient Data Store

BriefingCard Functionality in the CRM Web UI

$
0
0

This Blog post discusses about Briefing Card functionality in CRM Web UI. In this blog, I will briefly explain the steps that are required to implement this functionality.

 

When we are using a table view to display data in rows , in some cases customers can also have requirement to display additional data(Details) for that particular row. These details may be residing in another view .

 

Briefing Card functionality enables us to embed a view within row of a table. When the Expand button is clicked the embedded view is displayed .

 

An example implementation of Briefing Cards  can be seen in Territory Management.


In theTerritory Management Rules AB  2 rows can be seen . You can also see Expand/ Collapse button in the rows.

 

pic1.png

 

The 1st Row is now in the expanded state , and we can see additional details regarding the Rules.

 

 

pic2.png

 

The above functionality can be achieved by using briefing cards . You can see the implementation for the same in component MD110FDT_TMGMT

view RuleAccessVS.

 

I will explain the steps  briefly

 

Step 1 : Create a table view .

- Just follow the steps as you would do for creating any other Table View.

- Go to the .HTM page of the view and put the confing tags as shown below.

 

pic3.png

 

- From the above tags you can cleary make out that we are embedding view 'CUEXP.FDT_EXP/MainWindow ' , in view area 'DecisionTab'.

  This means here you can embed the view which you want to display when the user clicks on the 'Expand' button on the rows.

 

Step 2: Go to the Runtime Repository

 

- Include the view in the viewset. ( The trick here is that we are treating the view as a viewset)

- Create view area for the view. ( Yes you can do this for a view as well )

- Include the view that you need to embed , into the view area .

 

pic4.png

 

 

Step 3:  Handle EH_ONSELECT

 

- You need to handle Event SELECT and will need a event handler for this. When the user clicks on 'Expand/ Collapse ' Button i.e 'Open Briefing card/Close Briefing Card' you need to handle this event.

If your data binding is done correctly , then you may not have to do much here and the briefing card will be functional , with steps 1 and 2 only.

But if you have some complex requirements then  you may need to do coding here.

The complexity of  the coding in this event handler depends on the overall functionality that you are trying to implement .

Reading the actuall content from the Content Managment (CMBO)

$
0
0

Generally we store the attachments in CRM in the CMBO object which in turn stores the infomration in Content managment Server.

More infomration of Content managment is here http://help.sap.com/saphelp_crm70/helpdata/en/46/3ede33fddf2f91e10000000a1553f6/content.htm

 

But you may actually need to read the actuall content may be to attach it as a mail or display it etc..

 

May be this steps would help you.

1.png

1) For Exmaple you might have attachment which are generally stored in Content managment server (CMBO object at GENIL Level),

 

 

2) Every CMBO object would have the following relation with the following information.

2.png

 

3) We have a very usefull class which will work with this content management  CL_HRTMC_DOCUMENT_UTILS ,with very usefull method,just a glance.

3.png

 

4) You can use the sample code below for getting the infomation from the CMBO via this class.

 

data :  

    lr_cmbo                       TYPE REF TO cl_crm_bol_entity,
    lt_documents               TYPE STANDARD TABLE OF crmt_cmic_doc_attr,
    ls_documents              TYPE crmt_cmic_doc_attr,
    lr_data                         TYPE REF TO data,
    lr_crm_utility                TYPE REF TO cl_hrtmc_document_utils,
    lt_binary_documents   TYPE sdokobjects,
    ls_binary_documents   TYPE sdokobject,
    lt_contents                   TYPE hrtmc_t_document_content,
    ls_contents                  TYPE hrtmc_s_document_content.

 

   lr_cmbo = lr_entity_col->get_first( ).

  CHECK lr_cmbo IS BOUND.

  lr_data = lr_cmbo->get_properties_by_bpath( './CMBODocumentRefRel/*$'  ).

  CHECK lr_data IS NOT INITIAL.

  ASSIGN lr_data->* TO <fs_ref>.

  CHECK <fs_ref> IS ASSIGNED.

  lt_documents[] = <fs_ref>.

  CREATE OBJECT lr_crm_utility .

  LOOP AT lt_documents
          INTO ls_documents.

    CLEAR ls_binary_documents.
    REFRESH lt_binary_documents[].
    ls_binary_documents-class = ls_documents-loio_class.
    ls_binary_documents-objid = ls_documents-loio_objid.
    APPEND ls_binary_documents TO lt_binary_documents[].

    REFRESH lt_contents[].
    lr_crm_utility->get_content_of_documents( EXPORTING it_documents = lt_binary_documents[]
                                              IMPORTING et_contents  = lt_contents ).

    READ TABLE lt_contents[]
                INTO ls_contents
                INDEX 1.
    CHECK sy-subrc IS INITIAL.


    ls_body-content_bin   = ls_contents-content.
  

ls_contents-content. => This would have the content in the attachment or CMBO object in the Binary so you can play around this.

 

Thanks.

Viewing all 188 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>