Introduction
In my continuing quest to recreate some of the better user interface elements of the SAPGui for Windows/Classic Dynpro experience; I recently set out to try and recreate one of my personal favorites - the F1 field level help.
My goal was to recreate not just the context help, but also the technical information about the field that is exposed like in the classic dynpro. As we have developed large and complex BSP applications (especially very dynamic ones), the lack of some mechanism to identify what part of the code houses a particular element is greatly missed.
New!
Now you can download this document in PDF format and you can download a package with the code, class defintions, and screen shots.My search for this functionality actually began by studying some of the CRM BSP functionality that now is part of the Basis layer in WebAS 640. There is a lot of very impressive functionality in the CRM framework. Unfortunately the individual components are very dependent upon the CRM Framework. It was going to require considerable changes to try to adapt their implementation of F1 help for use as a standalone component.
Therefore I set out to create my own Field help control as a reusable BSP Extension Element. Although the finished solution is rather complex internally (like any generic object usually is), I wanted to make sure that the using the component was as simple as possible. To that end I decided to wrap my functionality to fire the field help around the HTMLB label element. I will generate a Hyperlink that will open the context help in a modal window when clicked. The final solution ended up being so simple to implement in your code that all you have to do is change the name of the element from label to f1Label if you are using Model View Binding. If you aren't using Binding or if you want to override the data element from the binding attribute, you only need to add on attribute in addition to the standard label attributes to provide this data element name. The easy that this new element can be introduced into existing views is especially important considering the amount of code that I want to go back and retrofit with this new functionality. Add to this that my company has a number of new developers just beginning to learn BSP. I also wanted to make this solution as approachable for this group as any of the other simple HTMLB elements.
Before we get started, I want to note that I developed this solution on WebAS 640 SP12. However looking over the solution I don't see anything that you shouldn't be able to implement in earlier support packages or even in WebAS 620.
The Solution
Let's have a look at the finished solution before we go any further into exploring the coding. First we will have a look at what the hyper linked labels look like in a sample application.
!https://weblogs.sdn.sap.com/weblogs/images/1918/F1_Appl.gif|height=258|alt=image|width=421|src=https...!
When we click on the label hyperlink we get basic browser modal window where we display two tabs. In the first and default tab, we have the Data Element Help itself. The Internal ITF (SAPScript) format for the Help has been converted to HTML.
Now you might notice the internal hyperlink in the example Help for material. In the converted HTML, this link actually points to a SAPEVENT. If you have ever done any programming for HTML content in the SAPGui HTML viewer you might remember that this is a special event that will be caught and returned to our Dynpro Event processing. However this SAPEVENT link is useless in the BSP context. Therefore we will have to convert this to a normal hyperlink to make it functional. Also most of these internal links point to glossary entries instead of Data Element texts. Therefore we will need internal processing in our Help Viewer to support the processing of both. The following is a screen shot of the help after we navigate through the material link.
Next up we have the second tab (and the one that as a developer I am more interested in). This is the tab that displays our technical information about the field in question. In order to get the maximum amount of information displayed here, you will obviously want to use Model View Binding for the BSP Extension Element. That way we will have visibility to the hosting Controller, View, Model Class, Model Attribute, Model Binding String, and the data element types for the field in question. The following is a screen shot for our Material Field information.
wrapping
design = me->design
for = me->for
required = me->required
text = me->text
tooltip = me->tooltip ).
****Render the Text label
WHILE m_page_context->element_process( element = label ) = co_element_continue.
ENDWHILE. "End label Render
ENDWHILE. "End Link Render
ELSE.
****Normal Label - no Link because we couldn't determine a data element
label ?= cl_htmlb_label=>factory(
design = me->design
encode = me->encode
for = me->for
id = me->id
id_postfix = '__F1'
labeledcontrolname = me->labeledcontrolname
labeltype = me->labeltype
required = me->required
text = me->text
textdirection = me->textdirection
tooltip = me->tooltip
width = me->width
wrapping = me->wrapping
design = me->design
for = me->for
required = me->required
text = me->text
tooltip = me->tooltip ).
****Render the Text label
WHILE m_page_context->element_process( element = label ) = co_element_continue.
ENDWHILE. "End label Render
ENDIF.
ENDMETHOD.
BSP Element Class Methods - resolve_model_binding
If you use model view binding, this method will determine the class and its attribute that correspond to the provided binding string. This method will also use the RTTS (RunTime Type System) to determine information about the model class and details about the model attribute data type.
get_relative_name( ).
ENDIF.
FOR-attribute
l_for = model->get_attribute_name( attribute_path = value_path ).
ID-attribute
IF id IS INITIAL.
CONCATENATE l_for '_l' INTO id.
ENDIF.
****Get Data Reference to bound data object
DATA: l_data TYPE REF TO data.
l_data = model->get_attribute_data_ref( attribute_path = value_path ).
CHECK l_data IS NOT INITIAL.
****Get the RTTI Drescriptor for this data reference
DATA: descriptor TYPE REF TO cl_abap_elemdescr.
descriptor ?= cl_abap_elemdescr=>describe_by_data_ref( l_data ).
****Read Data Dictionary information for this reference
DATA: flddescr TYPE dfies.
flddescr = descriptor->get_ddic_field( ).
me->dataelement = flddescr-rollname.
system_state->rollname = me->dataelement.
system_state->leng = flddescr-leng.
system_state->datatype = flddescr-datatype.
system_state->inttype = flddescr-inttype.
system_state->model_class = class_name.
ENDMETHOD.
BSP Element Class Methods - record_system_state
This is the final method of our Element Class. This method is responsible for completing the model class. It then serializes it to XML and writes the XML string into a server cookie for later consumption. Finally the method creates the URL with the included keys to read the server cookie that will point to the Field Help Modal BSP application.
m_page_name.
ENDIF.
DATA: ostream TYPE string,
xslt_err TYPE REF TO cx_xslt_exception.
serialize model class
TRY.
CALL TRANSFORMATION id
SOURCE model = system_state
RESULT XML ostream.
****Write cookie it into the Server Cookie
cl_bsp_server_side_cookie=>set_server_cookie( name = data_name
application_name = ''
application_namespace = ''
username = 'F1HELP'
session_id = mc_runtime->session_id
data_name = data_name
data_value = ostream
expiry_time_rel = '1200' ).
CATCH cx_xslt_exception INTO xslt_err.
ENDTRY.
****Send the Keys for the Model Class to the Popup via the URL
DATA: url TYPE string.
DATA: page TYPE string.
page = 'F1_Help.do'.
DATA: params TYPE tihttpnvp.
FIELD-SYMBOLS: rfcdest ).
if input is available, dispatch this input to subcomponent.
this call is only necessary for toplevel controllers.
( if this is not a toplevel controller or no input is present,
this call returns without any action)
dispatch_input( ).
if any of the controllers has requested a navigation,
do not try to display, but leave current processing
if is_navigation_requested( ) is not initial.
return.
endif.
****Call our View
view = create_view( view_name = 'F1_Help.bsp' ).
view->set_attribute( name = 'model' value = model2 ).
call_view( view ).
endmethod.
BSP F1 Help Controller Method - do_handle_event
This is our only other inherited method. This has our logic for event handling. We only have one event - the switch of the selected tab.
BSP F1 Help Controller Method - load_values_from_formfield
This method has our logic to read our Server Cookie Keys from the URL.
BSP F1 Help Controller Method - read_model
This method has our logic to restore our model class instance back from the Server Cookie.
method read_model.
*@7BQReturning@ VALUE( R_MODEL ) TYPE REF TO IF_BSP_MODEL BSP: Basis Interface for Models
data: istream type string,
xslt_err type ref to cx_xslt_exception.
Read Server cookie
call method cl_bsp_server_side_cookie=>get_server_cookie
exporting
name = data_name
application_name = ''
application_namespace = ''
username = 'F1HELP'
session_id = session_id
data_name = data_name
changing
data_value = istream.
deserialize the Class
if istream is not initial.
try.
call transformation id
source xml istream
result model = r_model.
catch cx_xslt_exception into xslt_err.
endtry.
endif.
endmethod.
Implementing The BSP F1 Help Application - Model
The final component in our Field Help BSP application is the Model Class. This class has all the logic to read our Field Help or Glossary Entry. It also has the logic to convert the SAPEVENT hyperlinks. Don't forget to include the IF_SERIALIZABLE_OBJECT interface in this class definition. This is the interface that will allow us to convert the class instance to XML.
BSP F1 Help Model - Attributes
The following are the definition for all the attributes for our model class. Many of the fields contain the system information that will be bound to our View. There are also some attributes used in the internal manipulation of the Help Text.
!spacer.gif|height=306|alt=|width=1|src=spacer.gif|border=0! | |
BSP F1 Help Model Local Declarations
There is an SAP provided local class that we will use later to convert our SAPScript Help to HTML. The following are the local declarations for that class.
BSP F1 Help Model Methods - Initialize
This is the main public method of this class. This method is called from the Controller and triggers all the Method processing. It sets the keys of the method and begins the reading of the help text.
BSP F1 Help Model Methods - call_rfc
This method will call the SAP Function modules to read the Help Text or Glossary Entry. You might notice some static method calls to a class instance called converter. My study of the CRM BSP extensions did pay off, because I was able to reuse this nice SAPScript to HTML converter class. The actual coding for the converter class is contained in an include so it was easy to integrate into my model class.
method call_rfc.
DATA: html_page TYPE TABLE OF htmlline.
data: html_page type w3htmltab.
data: msg_text(80) type c.
clear me->message.
clear me->html_string.
data: name type tdobname.
data: begriff type termbegr.
data: iline type table of tline.
data: ihead type thead.
if docuobject cp 'DE*'.
name = docuobject+2.
call function 'ABAP_DOCU_ITF_TO_HTML'
exporting
id = 'DE'
area = ''
name = name
file_flag = ''
changing
html = html_page
exceptions
docu_not_read = 1
others = 2.
if sy-subrc <> 0.
endif.
elseif docuobject cp 'GLOS*'.
begriff = docuobject+4.
call function 'GLOSSARY_READ'
exporting
begriff = begriff
sprache = sy-langu
owner = ''
importing
head = ihead
tables
iline = iline.
replace include texts, text symbols and control commands
call method converter=>replace_itf_text
exporting
p_header = ihead
file_flag = ''
changing
p_itf_text = iline.
my own itf-html conversion ...
call method converter=>conversion
exporting
name = ''
p_langu = sy-langu
file_flag = ''
link_prefix = ''
changing
itf = iline[]
html = html_page[].
endif.
field-symbols:
method build_url.
*@78QImporting@ I_NEW_ELEMENT TYPE STRING New Data Element Name
*@7BQReturning@ VALUE( R_URL ) TYPE STRING
****Send the Keys for the Model Class to the Popup via the URL
DATA: url TYPE string.
data: page type string.
page = 'F1_Help.do'.
data: params type tihttpnvp.
field-symbols:
I have tried to share this solution in considerable detail. I know that many people in the BSP community have developments such as this. They have reusable code (possibly in the form of BSP extension elements) that forms useful low level objects. I am hoping that others in the community will share their developments as well. I am interested if there was some way that we, as the SDN Community, could start some sort of code exchange for these types of elements. Perhaps long term there is even a way for the community to enhance and maintain such shared objects.