Web Dynpro ABAP provides an extensive set of UI Elements. In most cases standard UI Elements suit developer needs. If not, there is an option to create your own UI element, for example, with the help of HTML5 islands or Adobe Flash Islands. If you do not have Flex Builder knowledge or your system is not on right release level (7.31 SP5 for HLTML5 island) then IFrame UI Element is the only choice.
Lets say you have a requirement to display notes that users add to a document in form of a chat. Standard UI Elements like Table, FormattedTextView or TextView can not satisfy the requirement. It is easy to model Chat UI Element with the help of IFrame UI Element, InputField UI Element and some basic knowlege of HTML, CSS, JavaScript, XML and XSLT.
What it takes is:
1) Transform notes internal table into XML using Simple Transformation;
2) Tranform XML into HTML using XSLT transformation;
3) Save HTML document in repository;
4) Map HTML document URL into Source property of IFrame UI Element.
Here is how modeled Chat UI Element looks:
It is easy to using Modeled Chat UI Element - just key in text and press enter:
Below are step by step instructions how to implement the demo application:
1) In trx. XSLT_TOOL create ZIFRAME_DEMO_ST Simple Transformation that transforms note internal table data into XML
In Source Cde tab add following code:
<?sap.transform simple?>
<tt:transform xmlns:tt="http://www.sap.com/transformation-templates">
<tt:root name="NOTE"/>
<tt:template>
<ZIFRAME_DEMO>
<tt:loop ref=".NOTE" name="line">
<NOTE>
<CREATED_BY>
<tt:value ref="$line.CREATED_BY" />
</CREATED_BY>
<CREATED_ON>
<tt:value ref="$line.CREATED_ON" />
</CREATED_ON>
<CREATED_AT>
<tt:value ref="$line.CREATED_AT" />
</CREATED_AT>
<NOTE>
<tt:value ref="$line.NOTE" />
</NOTE>
</NOTE>
</tt:loop>
</ZIFRAME_DEMO>
</tt:template>
</tt:transform>
2) In trx. XSLT_TOOL create ZIFRAME_DEMO_XSLT XSLT Transformation that transforms XML to HTML
In Source Cde tab add following code:
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:sap="http://www.sap.com/sapxsl"
>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<html>
<head>
<script>
window.onload=toBottom;
function toBottom()
{
setTimeout(function(){window.scrollTo(0, document.body.scrollHeight);},250);
}
</script>
</head>
<style>
html {height: 100%; width:100%; padding:0px; margin:0px;}
body {background-color:#e7eff7; height:100%; width:100%; padding:0px; margin: 0px;border-style:solid;border-width:1px;border-color:#A5ADB5;}
table.props1 td { font-family:Arial,Helvetica,sans-serif; font-size: 0.7em; }
table.props { background:#999999; }
table.props td { background:#FFFFFF; padding:1 1; vertical-align:top; font:normal 10 verdana; padding-left=4px; padding-right=4px; }
table.props th { background:#EEEEEE; padding:1 1; vertical-align:top; font:normal 10 verdana; padding-left=4px; padding-right=4px; }
</style>
<body >
<table class="props1" width="100%">
<xsl:for-each select="ZIFRAME_DEMO/NOTE">
<tr>
<td title="{CREATED_BY}" width="120p" style="color:#296394;vertical-align:top;"><xsl:value-of select="CREATED_BY"/>
<br/><xsl:value-of select="CREATED_ON"/><xsl:text> </xsl:text><xsl:value-of select="CREATED_AT"/></td>
<td valign="top"><xsl:value-of select="NOTE"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:transform>
Note: XSLT transformation formats output using HTML and CSS and also scrolls to last note using JavaScript
3) Create ZIFRAME_DEMO Component
4) Add NOTE context node to MAIN view.
Set cardinality of NOTE node to 0..n, then CREATED_BY, CREATED_ON, CREATED_AT and NOTE attributes of types NAME1, DATS, TIMS and STRING respectively
5) Add NOTE_URL attribute to MAIN view context. Set type to STRING.
6) Add NOTE_NEW attribute to MAIN view context. Set type to STRING
7) On MAIN view set ROOTUIELEMENTCONTAINER UI Element layout to MatrixLayout
8) Add IFRAME UI element to MAIN view layout. Set Layout Data to MatrixHeadData, set width to 400px and map Source to MAIN.NOTE_URL
9) Add INPUTFIELD UI element. Layout Data to MatrixHeadData, set width to 400px, map Value to MAIN.NOTE_NEW, create ENTER action and assign it to onEnter event (it will be implemented later).
10) Create GET_HTML method of MAIN view. This method Note data into XML and then into HTML.
METHOD get_html.
DATA: w_xmlTYPE string.
* Transform Note data into XML
CALL TRANSFORMATIONziframe_demo_st
SOURCE note = it_note
RESULTXMLw_xml.
* Transform XML into HTML
CALL TRANSFORMATIONziframe_demo_xslt
SOURCEXMLw_xml
RESULTXMLrv_html.
ENDMETHOD.
11) Create GET_URL method in MAIN view. This method creates HTML document in respository and returns its URL.
METHOD get_url.
DATA: cached_responseTYPE REF TO if_http_response.
DATA: w_guidTYPE guid_32.
DATA: w_urlTYPE string.
* Creat response object
CREATE OBJECTcached_response
TYPE
cl_http_response
EXPORTING add_c_msg = 1.
TRY. " ignore, if compression can not be switched on
CALL METHOD cached_response->set_compression
EXPORTING options = cached_response->co_compress_based_on_mime_type
EXCEPTIONS
OTHERS = 1.
CATCH cx_root.
ENDTRY.
* Set response object header and data
cached_response->set_cdata( iv_html).
cached_response->set_header_field( name = if_http_header_fields=>content_type
value = 'text/html' ).
cached_response->set_status( code = 200 reason = 'OK' ).
cached_response->server_cache_expire_rel( expires_rel = 3600 ).
* Generate URL
CALL FUNCTION 'GUID_CREATE'
IMPORTING
ev_guid_32 = w_guid.
CONCATENATE '/sap/public/' w_guid'.' 'html' INTO rv_url.
* Cache the URL
cl_http_server=>server_cache_upload( url = rv_url
response = cached_response ).
ENDMETHOD.
12) Implement WDDOINIT method of MAIN view. This method initializes IFRAME with notes
METHOD wddoinit.
DATA: w_html TYPE string,
w_url TYPE string.
DATA: wa_note TYPE wd_this->element_note,
wt_note TYPE wd_this->elements_note.
DATA: node_note TYPE REF TO if_wd_context_node.
DATA: w_note_1 TYPE string,
w_note_2 TYPE string,
w_note_3 TYPE string,
w_note_4 TYPE string,
w_note_5 TYPE string,
w_note_6 TYPE string.
CONCATENATE: 'Web Dynpro ABAP provides an extensive set of UI Elements.'
'In most cases standard UI Elements suit developer needs.'
'If not, there are options to create your own UI element,'
'for example, with the help of HTML5 islands or Adobe Flash Islands.'
'If you do not have Flex Builder knowledge or your system is not on right release level'
'(7.31 SP5 for HLTML5 island) then IFrame UI Element is your only option.' INTO w_note_1 SEPARATED BY SPACE,
'Lets say you have a requirement to display notes that users add to a document in form of a chat.'
'Standard UI Elements like Table, FormattedTextView or TextView can satisfy the requirement.'
'It is easy to model Chat UI Element with the help of IFrame UI Element and some basic knowlege of HTML, CSS, JavaScript, XML and XSLT.'
'What it takes:' INTO w_note_2 SEPARATED BY SPACE.
w_note_3 = '1) Serialize notes internal into XML form using Simple Transformation;'.
w_note_4 = '2) Tranform XML into HTML using XSLT transformation;'.
w_note_5 = '3) Save HTML document in repository;'.
w_note_6 = '4) Map HTML document URL into Source property of IFrame UI Element'.
* Set initial notes
wa_note-created_by = 'Uladzislau Pralat'.
wa_note-created_on = '20140924'.
wa_note-created_at = 135903.
wa_note-note = w_note_1.
APPEND wa_note TO wt_note.
wa_note-note = w_note_2.
APPEND wa_note TO wt_note.
wa_note-note = w_note_3.
APPEND wa_note TO wt_note.
wa_note-note = w_note_4.
APPEND wa_note TO wt_note.
wa_note-note = w_note_5.
APPEND wa_note TO wt_note.
wa_note-note = w_note_6.
APPEND wa_note TO wt_note.
node_note = wd_context->get_child_node( wd_this->wdctx_note ).
node_note->bind_table( wt_note ).
* Generate HTML
w_html = get_html( wt_note ).
* Generate URL
w_url = get_url( w_html ).
* Bind URL to IFrame
wd_context->set_attribute( name = 'NOTE_URL'
value = w_url ).
ENDMETHOD.
13) Implement ONACTIONENTER method of MAIN view to reach on ENTER action. This method adds new note to IFRAME and clears INPUTFIELD.
METHOD onactionenter.
DATA: w_htmlTYPE string,
w_url TYPE string.
DATA: w_note_newTYPE wd_this->element_context-note_new.
DATA: ws_noteTYPE wd_this->element_note,
wt_noteTYPE wd_this->elements_note.
DATA: node_noteTYPE REF TO if_wd_context_node.
DATA: element_noteTYPE REF TO if_wd_context_element.
* Get new note
wd_context->get_attribute( EXPORTING name = 'NOTE_NEW'
IMPORTING value= w_note_new).
* Add new note to context
node_note= wd_context->get_child_node( wd_this->wdctx_note).
element_note= node_note->create_element( ).
ws_note-created_by= 'Uladzislau Pralat'.
ws_note-created_on= sy-datum.
ws_note-created_at= sy-uzeit.
ws_note-note = w_note_new.
element_note->set_static_attributes( ws_note).
node_note->bind_element( new_item = element_note
set_initial_elements= abap_false).
* Get all notes from context
node_note->get_static_attributes_table( IMPORTING table= wt_note ).
* Generate HTML
w_html= get_html( wt_note).
* Generate URL
w_url= get_url( w_html).
* Bind URL to IFrame
wd_context->set_attribute( name = 'NOTE_URL'
value= w_url).
* Clear new note
wd_context->set_attribute( name = 'NOTE_NEW'
value= SPACE ).
ENDMETHOD.