This tutorial shows how you can translate a text in Web Dynpro if you don't use a text from a Text Element from the Assistance Class. It also shows how you can create your own Value Help dynamic at Runtime which are bind to a DropDownByKey
This tutorial shows how you can translate a text in Web Dynpro if you don't use a text from a Text Element from the Assistance Class. It also shows how you can create your own Value Help dynamic at Runtime which are bind to a DropDownByKey
This tutorial shows how you can use the Object Value Selector Component. This helps you when you want to rewrite the F4 Value Help of a field, or you just want to create a F4 Help for a field.
This tutorial shows how you can create dynamically a node and also a table. It is also shown how you can bind the table with the dynamically created node. It is ABAP Web Dynpro Dynamic Programming. It simulates the behaviour of the SE16.
This tutorial shows how you can play with the Properties of an UI Element in Web Dynpro. With the read only, enabled and visible.
Hi,
I thought to have a ready code and share with all, this will help anyone who is dealing with ALV in Web dynpro ABAP.
Please find the below working and tested code.
The code will allow you to change the description of the columns, Hide/display standard functions buttons, use standard function like adding etc. Have a look at the code below. Let me know in case of any further queries.
****ALV standard declarations
DATA: LO_CMP_USAGE TYPEREFTO IF_WD_COMPONENT_USAGE,
LO_INTERFACECONTROLLER TYPEREFTO IWCI_SALV_WD_TABLE,
LV_VALUE TYPEREFTO CL_SALV_WD_CONFIG_TABLE.
DATA: LR_COLUMN_SETTINGS TYPEREFTO IF_SALV_WD_COLUMN_SETTINGS,
LR_COLUMN TYPEREFTO CL_SALV_WD_COLUMN,
LR_COLUMN_HEADER TYPEREFTO CL_SALV_WD_COLUMN_HEADER.
DATA: LT_COLUMNS TYPE SALV_WD_T_COLUMN_REF,
LS_COLUMNS TYPE SALV_WD_S_COLUMN_REF.
DATA: LR_STANDARD_FUNCTIONS TYPEREFTO IF_SALV_WD_STD_FUNCTIONS.
DATA: LR_ALV_HEADER TYPEREFTO CL_SALV_WD_COLUMN_HEADER,
LR_ALV_CONFIG TYPEREFTO CL_SALV_WD_CONFIG_TABLE.
DATA: LR_FIELD_AMNT TYPEREFTO CL_SALV_WD_FIELD.
DATA: LR_FIELD TYPEREFTO CL_SALV_WD_FIELD.
DATA: LV_AGGR_RULE TYPEREFTO CL_SALV_WD_AGGR_RULE.
DATA: LR_SORT_RULE TYPEREFTO CL_SALV_WD_SORT_RULE.
****create ALV component
LO_CMP_USAGE = WD_THIS->WD_CPUSE_ALV_COMP( ).
IF LO_CMP_USAGE->HAS_ACTIVE_COMPONENT( ) ISINITIAL.
LO_CMP_USAGE->CREATE_COMPONENT( ).
ENDIF.
****set data
LO_INTERFACECONTROLLER = WD_THIS->WD_CPIFC_ALV_COMP( ).
****ref to if_wd_context_node
LO_INTERFACECONTROLLER->SET_DATA(
R_NODE_DATA = LO_ND_CTX_VN_PLAN_OUPUT
).
LV_VALUE = LO_INTERFACECONTROLLER->GET_MODEL(
).
****implement standard functions and initializaton
LV_VALUE->IF_SALV_WD_TABLE_SETTINGS~SET_MULTI_COLUMN_SORT( VALUE = ABAP_TRUE ).
LR_STANDARD_FUNCTIONS ?= LV_VALUE.
LR_STANDARD_FUNCTIONS->SET_EXPORT_ALLOWED( ABAP_TRUE ).
LR_STANDARD_FUNCTIONS->SET_PDF_ALLOWED( ABAP_FALSE ).
LR_STANDARD_FUNCTIONS->SET_EDIT_CHECK_AVAILABLE( ABAP_FALSE ).
LR_STANDARD_FUNCTIONS->SET_EDIT_INSERT_ROW_ALLOWED( ABAP_FALSE ).
LR_STANDARD_FUNCTIONS->SET_EDIT_DELETE_ROW_ALLOWED( ABAP_FALSE ).
LR_STANDARD_FUNCTIONS->SET_EDIT_APPEND_ROW_ALLOWED( ABAP_FALSE ).
LR_STANDARD_FUNCTIONS->SET_VIEW_LIST_ALLOWED( ABAP_TRUE ).
LR_STANDARD_FUNCTIONS->SET_FILTER_FILTERLINE_ALLOWED( ABAP_TRUE ).
LR_STANDARD_FUNCTIONS->SET_DIALOG_SETTINGS_ALLOWED( ABAP_TRUE ).
LR_STANDARD_FUNCTIONS->SET_COLUMN_SELECTION_ALLOWED( ABAP_TRUE ).
LR_STANDARD_FUNCTIONS->SET_AGGREGATION_ALLOWED( ABAP_TRUE ).
LR_STANDARD_FUNCTIONS->SET_GROUP_AGGREGATION_ALLOWED( ABAP_TRUE ).
LR_STANDARD_FUNCTIONS->SET_COUNT_RECORDS_ALLOWED( ABAP_TRUE ).
LR_STANDARD_FUNCTIONS->SET_HIERARCHY_ALLOWED( ABAP_TRUE ).
LR_STANDARD_FUNCTIONS->SET_SORT_HEADERCLICK_ALLOWED( ABAP_FALSE ).
LR_STANDARD_FUNCTIONS->SET_SORT_COMPLEX_ALLOWED( ABAP_TRUE ).
****configure columns & column funtions
LR_COLUMN_SETTINGS ?= LV_VALUE.
LT_COLUMNS = LR_COLUMN_SETTINGS->GET_COLUMNS( ).
****setting column header for all display feilds
LR_COLUMN = LV_VALUE->IF_SALV_WD_COLUMN_SETTINGS~GET_COLUMN( 'AUFNR' ).
LR_ALV_HEADER = LR_COLUMN->GET_HEADER( ).
LR_ALV_HEADER->SET_DDIC_BINDING_FIELD( IF_SALV_WD_C_DDIC_BINDING=>DDIC_BIND_NONE ).
LR_ALV_HEADER->SET_TEXT( 'PO No').
LR_ALV_HEADER->SET_HEADER_TEXT_WRAPPING( ABAP_TRUE ).
LR_COLUMN = LV_VALUE->IF_SALV_WD_COLUMN_SETTINGS~GET_COLUMN( 'ATWRT_LEN' ).
LR_ALV_HEADER = LR_COLUMN->GET_HEADER( ).
LR_ALV_HEADER->SET_DDIC_BINDING_FIELD( IF_SALV_WD_C_DDIC_BINDING=>DDIC_BIND_NONE ).
LR_ALV_HEADER->SET_TEXT( 'Order Length(Mtr)').
LR_ALV_HEADER->SET_HEADER_TEXT_WRAPPING( ABAP_TRUE ).
LR_COLUMN = LV_VALUE->IF_SALV_WD_COLUMN_SETTINGS~GET_COLUMN( 'ATWRT_PLAN_QTY' ).
LR_ALV_HEADER = LR_COLUMN->GET_HEADER( ).
LR_ALV_HEADER->SET_DDIC_BINDING_FIELD( IF_SALV_WD_C_DDIC_BINDING=>DDIC_BIND_NONE ).
LR_ALV_HEADER->SET_TEXT( 'Plan Qty').
LR_ALV_HEADER->SET_HEADER_TEXT_WRAPPING( ABAP_TRUE ).
LOOPAT LT_COLUMNS INTO LS_COLUMNS.
****hide fields such as CUOBJ, MATNR, AUFPL from display
CASE LS_COLUMNS-ID.
WHEN'CUOBJ'.
LS_COLUMNS-R_COLUMN->SET_VISIBLE( IF_WDL_CORE=>VISIBILITY_NONE ).
WHEN'MATNR'.
LS_COLUMNS-R_COLUMN->SET_VISIBLE( IF_WDL_CORE=>VISIBILITY_NONE ).
WHEN'AUFPL'.
LS_COLUMNS-R_COLUMN->SET_VISIBLE( IF_WDL_CORE=>VISIBILITY_NONE ).
ENDCASE.
ENDLOOP.
****set row count at initial display as 30 rows
****hide all empty rows
LV_VALUE->IF_SALV_WD_TABLE_SETTINGS~SET_VISIBLE_ROW_COUNT( '30' ).
LV_VALUE->IF_SALV_WD_TABLE_SETTINGS~SET_DISPLAY_EMPTY_ROWS( VALUE = ABAP_FALSE ).
ENDIF.
Hi everyone,
Often when we need to print a Web Dynpro View, we can just use the browser's built-in printing method (Ctrl+P). Issue will arise if the contents in our Web Dynpro View are not fully displayed in the printed page. For example, an Text Edit that required us to scroll through to view all the contents.
To solve this problem, we may want to change the Text Edit dynamically to show all the text without scrolling. And yes, we will need to use Dynamic Programming to achieve this.
Before attempt to change the Text Edit size dynamically, we need to figure out how to derive the required size of the Text Edit such that all the text inside will be shown in Printing Mode.
So for example, our original content is like below screenshot:
Notice that there is a scroll bar and we won't be able to see all of the text when we print the page. Now let say we click on Resize button and we want the page to look like this.
With this, we are able to print the page with all content displayed.
Look at Text Edit's properties, it seems that the unit of the cols is by "Number of Letter" and the unit of rows is literally "Number of Rows". From this we can derive how to calculate the rows needed to display text without scrolling:
Rows Needed = Length(Value in Text Edit) / Number of Columns + 1
We add 1 to make sure that there is no scrollable contents. And with this, our problem is solved.
Now we come to the coding part.
Dynamically changing UI elements in Web Dynpro can be done in the hook method WDDOMODIFYVIEW (before the View get rendered). So let say when we click on the Resize button, an Action will be triggered, in the Action, we set a flag states that we want to resize the UI. This chain of events will eventually reach WDDOMODIFYVIEW. And here is our code in WDDOMODIFYVIEW:
METHOD wddomodifyview .
DATA: lr_container TYPE REF TO cl_wd_uielement_container,
lt_ui_children TYPE cl_wd_uielement=>tt_uielement,
lr_text_edit TYPE REF TO cl_wd_text_edit,
lv_value TYPE string,
lv_rows TYPE i,
lv_val_len TYPE i,
lv_cols TYPE i.
FIELD-SYMBOLS: <ls_ui> TYPE REF TO cl_wd_uielement.
IF first_time EQ abap_false AND wd_this->print_mode = abap_true.
"Get all UI elements in the root container
lr_container ?= view->get_element( 'ROOTUIELEMENTCONTAINER' ).
lt_ui_children = lr_container->get_children( ).
"Filter the ones that need to be tweaked in size
IF lt_ui_children IS NOT INITIAL.
LOOP AT lt_ui_children ASSIGNING <ls_ui>.
CLEAR: lv_rows, lv_cols, lv_value, lv_val_len.
"Down cast UI element to UI Text_Edit, skip the loop if it's not
TRY.
lr_text_edit ?= <ls_ui>.
lv_value = lr_text_edit->get_value( ).
lv_val_len = STRLEN( lv_value ).
lv_cols = lr_text_edit->get_cols( ).
lv_rows = lv_val_len / lv_cols.
lv_rows = lv_rows + 1.
IF lv_rows > 5.
lr_text_edit->set_rows( lv_rows ).
ENDIF.
CATCH cx_sy_move_cast_error.
CONTINUE.
ENDTRY.
ENDLOOP.
ENDIF.
wd_this->print_mode = abap_false.
ENDIF.
ENDMETHOD.
The above code is just for demonstration in blog purposes, few thoughts for it:
- The code is generic enough to cover for all Text Edits in our Web Dynpro view
- We can also extend the logic to cover for resizing other UI elements
- We may want to set a default rows value and bind the rows properties of our Text Edit to it
- We should also cater for case when user want to return to original view
- There's no "INSTANCE OF" in ABAP
That's end of the blog. Please comment and share if you know of other efficient method to print the Web Dynpro view.
Thanks much for reading. Cheers!
Recently I am working on a customer project and one customer requirement is they do not want to the word document be editable in the word control.
That means all buttons and menus in toolbar should be disabled.
The first idea comes to my mind is the flag "enableReadWrite".
As documented in sap help,it can fulfill my help but unfortunately it is deprecated. Regardless of this warning I have a try and found it does not work indeed.
Then I am speculating that if the document uploaded is read only, it is for sure that the toolbar will be disabled. So the issue turns to that how could I mark the document to be read only on the fly during uploading.
Since word 2007 the format of MS office follows the so called "Open office" protocal whose specification could be found here.
if you change the file type extension from .docx to .zip and open it with WinRAR, you will find the document is actually a bundle of several single files ( called document part in SAP internal ). The editability is controlled within the file settings.xml.
if you don't know the exact syntax, just google it. I use the explaination from this one in google:
Now the task is quite easy, just add the necessary xml tag into the document source code. You do not need to manually parse the document source code since SAP has already done this job. You can just reuse standard class CL_DOCX_DOCUMENT.
Since I need to insert the document protection node in "settings" node, a simple transformation is written for this. The magic is between line 18 and 21.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:sl="http://schemas.openxmlformats.org/schemaLibrary/2006/main" mc:Ignorable="w14" version="1.0"> <xsl:output encoding="UTF-8" indent="no" method="xml" omit-xml-declaration="no" version="1.0"/> <!-- Match everything all nodes and attributes --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="w:settings"> <xsl:element name="w:settings"> <xsl:for-each select="@*"> <xsl:copy/> </xsl:for-each> <xsl:element name="w:documentProtection"> <xsl:attribute name="w:edit">readOnly</xsl:attribute> <xsl:attribute name="w:enforcement">1</xsl:attribute> </xsl:element> <xsl:copy-of select="./*"/> </xsl:element> </xsl:template></xsl:stylesheet>
and find a proper place to call the transformation:
DATA: lr_element TYPE REF TO if_wd_context_element, lv_file_data TYPE xstring, lv_ret TYPE i, lx_temp TYPE xstring, lv_msg TYPE string, lt_parms TYPE /ipro/tt_key_value_pair, ls_parm LIKE LINE OF lt_parms. lr_element = me->wd_context->get_element( ). CHECK lr_element IS NOT INITIAL. lr_element->get_attribute( EXPORTING name = 'BINARY' IMPORTING value = lv_file_data ). DATA(lo_docx) = cl_docx_document=>load_document( lv_file_data ). DATA(lo_main_part) = lo_docx->get_maindocumentpart( ). DATA(lo_docx_settings) = lo_main_part->get_documentsettingspart( ). DATA(lx_settings) = lo_docx_settings->get_data( ). /ipro/cl_docx_utilities=>transform( EXPORTING iv_input_xstring = lx_settings iv_transform_name = '/IPRO/DOCXCC_PROTECT' it_parameters = lt_parms IMPORTING ev_result = lx_temp ev_ret = lv_ret ev_message = lv_msg ). lo_docx_settings->feed_data( lx_temp ). DATA(lx_docx_package) = lo_docx->get_package_data( ). lr_element->set_attribute( EXPORTING name = 'BINARY' value = lx_docx_package ).
after that the tag will be there in settings.xml:
The word control before upload document looks like below, buttons and menus available:
After upload, menu and button are disabled. If you try to edit the document, there will be notifications in the right pane to give you a hint that is not possible.
Of course this solution does not work for lower version of MS word like word2003. Fortunately my customer has enough money and they are already using Office 2013 so I do not need to worry about it
Summary: This article illustrates the possibility of doing mass processing in POWL
In one of my projects there was a requirement wherein the user should be able to process up to 5 different work orders/operations at the same time. These work orders will be selected from a power list(POWL) in portal.
The standard POWL behavior throws an error message on certain actions if more than one rows are selected. This behavior can be overridden by creating an implicit enhancement in the respective feeder class.
Feeder class
The feeder class is the central and the most important place while developing and modifying Power Lists. The feeder class includes the handling of actions initiated by the user while pressing a button.
How to find the feeder class used for your POWL. (reference http://scn.sap.com/thread/1983141 )
Method 1 : T-code POWL_TYPE contains the Feeder class name assigned to the POWL type .
One can check the POWL type with description and find the feeder class associated with it and then put a break point in method IF_POWL_FEEDER~GET_OBJECT_DEFINITION of the feeder class and ensure that feeder class is correct.
Or Method 2: Go to POWL_UI_COMP webdynpro component, navigate to MASTER_CONTENT view method tab .
In the ONACTIONREFRESH_CURRENT event in the method tab set a break point in the lr_model->refresh_current( ). Click the "Refresh" button from the POWL table of which you want to find the feeder class , you will get the POWL type inside the method ( variable name- ms_current_query-type ). Now go to POWL_TYPE t-code and find the feeder class which is assigned to this POWL TYPE
Mass selection
Create an implicit enhancement at the end of the method IF_POWL_FEEDER~HANDLE_ACTION of your feeder class. Code snippet given below.
i_actionid is the action for which you need to select more than one rows in POWL. In this example i_actionid='CONF' for the 'Enter Confirmation' button from the screenshot above.
The selected orders/operations are stored in a transaction table ZTI_PMCONF for the current logged in user.
ENHANCEMENT 1 ZPMZCONF_POWL_CL. "active version *
DATA ls_order_op type ZTI_PMCONF.
DATA ltt_powl_msg TYPE POWL_MSG_TTY.
IF lv_selected GT 5 AND i_action_index IS INITIAL AND mv_bp_version NE '10' AND i_actionid = 'CONF'.
** display error message "Select upto 5 rows only" if more than 5 work orders are selected in POWL
delete lt_powl_msg index 1.
e_messages[] = lt_powl_msg[].
ls_powl_msg-msgtype = cl_rplm_qimt_co=>sc_error.
ls_powl_msg-msgid = 'ZZPM'.
ls_powl_msg-msgnumber = '144'.
APPEND ls_powl_msg TO lt_powl_msg.
e_messages[] = lt_powl_msg[].
ELSEIF lv_selected <> 1 AND i_action_index IS INITIAL AND mv_bp_version NE '10' AND i_actionid = 'CONF'.
** suppress standard error message "Select one line only" to allow multiple line selections for this action
delete lt_powl_msg index 1.
e_messages[] = lt_powl_msg[].
** delete all the previous user selections stored in the transaction table if any, this is also deleted immediately after the values are set in the application
DELETE FROM ZTI_PMCONF WHERE UNAME eq sy-uname.
COMMIT WORK.
DATA lv_tab TYPE sy-tabix.
lv_tab = 0.
** Loop through the number of selected lines
DO lv_selected TIMES.
lv_tabix = lv_tab + 1.
READ TABLE c_selected INTO ls_index INDEX lv_tabix.
READ TABLE c_result_tab INTO ls_result INDEX ls_index-tabix.
** Check if order is locked
CALL METHOD me->check_order_lock
EXPORTING
iv_aufnr = ls_result-aufnr
IMPORTING
e_messages = ltt_powl_msg.
IF ltt_powl_msg IS NOT INITIAL.
LOOP AT ltt_powl_msg INTO ls_powl_msg.
APPEND ls_powl_msg TO lt_powl_msg.
ENDLOOP.
ENDIF.
** if there are no errors or no work orders are locked, save the selected work orders and operation in the database table ZTI_PMCONF
IF lt_powl_msg IS INITIAL.
ls_order_op-AUFNR = ls_result-aufnr.
ls_order_op-VORNR = ls_result-vornr.
ls_order_op-UNAME = sy-uname.
INSERT INTO ZTI_PMCONF VALUES ls_order_op.
clear ls_order_op.
ENDIF.
lv_tab = lv_tab + 1.
ENDDO.
IF lt_powl_msg IS INITIAL.
** Get role id
IF i_applid = cl_rplm_qimt_co=>sc_applid_mt.
lv_role_id = cl_rplm_qimt_co=>sc_roleid_mt_compl_conf.
ELSE.
lv_role_id = cl_rplm_qimt_co=>sc_roleid_others.
ENDIF.
** Get POWL api
cl_powl_runtime_services=>get_powl_object_info_handle(
RECEIVING
ro_powl_object_info_handle = lo_obj_info
EXCEPTIONS
no_wdr_component = 1
OTHERS = 2 ).
IF sy-subrc = 0 AND lo_obj_info IS NOT INITIAL.
lv_environment = lo_obj_info->mv_client_environment.
ENDIF.
** The custom form developed for this requirement(not in scope of this article) can be accessed via second level navigation or from the POWL
worklist. It behaves differently in both cases, so to identify if it is called via second level navigation or via POWL, a parameter is passed which is read in the HANDLEDEFAULT method of the window
** set parameter POWL_FLAG to check if the application is being called via POWL or second level navigation
ls_name_value-key = 'POWL_FLAG'.
ls_name_value-value = 'X'.
INSERT ls_name_value INTO TABLE lt_name_value.
ls_powl_follow_up-bo_system = cl_rplm_qimt_co=>sc_system_erp.
IF lv_environment NE if_wd_application=>co_client_environment-nwbc.
ls_powl_follow_up-bo_name = 'maintenance_order_confirmation'.
ELSE. "PFCG usage in NWBC
ls_powl_follow_up-bo_name = 'maintenance_ord_conf'.
ENDIF.
ls_powl_follow_up-bo_op_name = 'create'.
ls_powl_follow_up-parameters = lt_name_value.
ENDIF.
e_portal_actions = ls_powl_follow_up.
*----------------------------------------------------------------------*
*- Return the message table
*----------------------------------------------------------------------*
e_messages[] = lt_powl_msg[].
ENDIF.
ENDENHANCEMENT.
Note: I tried using a singleton class for this approach instead of using a transaction table. However, the session is not retained across POWL and the custom application.
Summary:
Enable filter Line on table by default on POWL application.
Requirement:
In the standard behavior POWL will show filter on table after you click on filter link on the right hand top side of the table. With the same link we can show or hide the filter option on table.
But if we have a requirement to show the filter option on table by default, here is the solution for POWL or other webdynpro supported applications.
Solution: Steps to implement the solution:
This functionality exists in POWL_TABLE_COMP webdynpro component.
Go to POWL_TABLE_COMP à Navigate to view à Method : DO_HOUSEKEEPING
Now implement overwrite exist enhancement to this method as follows.
Click on respective button under overwrite column.
And click on Enhancement button.
Now create enhancement as below.
Every time you do modification always recommended to use the same enhancement for the one functionality chance.
Now go to overwrite page and copy of all code from the original method. And go to overwrite method and copy all the code.
Now trace/debug for exact location to implement your functionality. In this case copy the below code after line no: 42.
lr_alv_model->if_salv_wd_std_functions~set_filter_filterline_allowed( abap_true ).
lr_alv_model->if_salv_wd_std_functions~set_filter_complex_allowed( abap_true ).
IF first_time IS NOT INITIAL.
cl_salv_wd_model_table_util=>if_salv_wd_table_util_funcs~set_functions_visible(
r_model = lr_alv_model
VALUE = cl_wd_uielement=>e_visible-none ).
ELSE.
cl_salv_wd_model_table_util=>if_salv_wd_table_util_funcs~set_functions_visible(
r_model = lr_alv_model
VALUE = cl_wd_uielement=>e_visible-visible ).
ENDIF.
Now execute the POWL and we can see the filter line on the table for all queries.
KEEP SHARING
Venky
Hello everyone,
in my first post I would like to present a way to check if required fields are filled. Below you will find data declaration, that will be used:
DATA: l_node TYPE REF TO if_wd_context_node,
l_attr_list TYPE cl_wd_dynamic_tool=>t_check_mandattr_tab,
l_attr TYPE cl_wd_dynamic_tool=>t_check_mandattr_struct,
l_has_errors TYPE wdy_boolean.
Reference to node (l_node) which attributes will be checked, list of attributes (l_attr_list) and a flag (l_has_errors) to indicate if check was with errors.
The next step is to fill list with attribute name(s):
l_attr-node_path = wd_this->wdctx_pmb_md_edit.
l_attr-element_index = -1.
l_attr-attribute_name = 'KTEXT'.
APPEND l_attr TO l_attr_list.
*here more attributes can be filled if needed
*check for required fields
l_has_errors = cl_wd_dynamic_tool=>check_mandatory_attributes(
attribute_list = l_attr_list
display_messages = abap_true
context_root = wd_context ).
IF l_has_errors EQ 'X'.
EXIT.
ENDIF.
I hope you will find it useful.
Best regards,
Paul
Hi,
I have come across many scn threads which refer to "How to read / get data from a dynamic node" .
Here I would like to demonstrate, the steps to read the data from a node ( either static / dynamic node ) in Webdynpro ABAP.
I have divided the task into 3 methods
Now, let us look into the code of each method as below
GET_NODE_INFO( )
Parameters:
Parameter | Type | Ref To | Optional | Associated Type | Description |
---|---|---|---|---|---|
ID_NODE_NAME | Importing | STRING | Node Name | ||
IO_PARENT_NODE | Importing | Checked | Yes | IF_WD_CONTEXT_NODE | Parent Node Reference |
EO_NODE_INFO | Exporting | Checked | IF_WD_CONTEXT_NODE_INFO | Node info reference | |
ED_ERROR_MESSAGE | Exporting | STRING | error message | ||
EO_NODE | Exporting | Checked | IF_WD_CONTEXT_NODE | Node reference |
Logic:
METHOD get_node_info .
DATA: lo_node_info TYPE REF TO if_wd_context_node_info,
lo_parent_node TYPE REF TO if_wd_context_node,
lv_node_name TYPE string,
lx_root TYPE REF TO cx_root.
TRY.
"=============================================
" check if node name is supplied,
" if so nothing do , return the control
"=============================================
IF id_node_name IS INITIAL.
RETURN.
ELSE.
lv_node_name = id_node_name.
TRANSLATE lv_node_name TO UPPER CASE.
ENDIF.
"=============================================
" Check if io_parent_node is not bound, if so
" Assume parent node is WD_CONTEXT
"=============================================
IF io_parent_node IS NOT BOUND.
lo_parent_node = wd_context.
ELSE.
lo_parent_node = io_parent_node.
ENDIF.
"=============================================
"get node info
"=============================================
eo_node = lo_parent_node->get_child_node( name = lv_node_name ).
eo_node_info = eo_node->get_node_info( ).
CATCH cx_root INTO lx_root.
ed_error_message = lx_root->get_text( ).
ENDTRY.
ENDMETHOD.
----------------------------------------------------------
GET_NODE_DATA_TYPE( )
Parameters:
Parameter | Type | Ref To | Optional | Associated Type | Description |
---|---|---|---|---|---|
IO_NODE_INFO | Importing | Checked | IF_WD_CONTEXT_NODE_INFO | Node info Reference | |
ED_ERROR_MESSAGE | Exporting | STRING | Error message | ||
EO_DATA | Exporting | Checked | DATA | Node data type ref | |
ET_FCAT | Exporting | LVC_T_FCAT | Attributes/fields list |
Logic:
METHOD GET_NODE_DATA_TYPE .
CLEAR:
eo_data,
et_fcat,
ed_error_message.
TRY .
DATA:
lo_table TYPE REF TO data,
ls_fcat TYPE lvc_s_fcat,
lt_attr TYPE wdr_context_attr_info_map,
ls_attr LIKE LINE OF lt_attr,
lx_root TYPE REF TO cx_root.
IF io_node_info IS NOT BOUND.
ed_error_message = 'Node info is invalid'.
RETURN.
ENDIF.
"=============================================
" get attributes
"=============================================
lt_attr = io_node_info->get_attributes( ).
LOOP AT lt_attr INTO ls_attr.
CLEAR ls_fcat.
ls_fcat-fieldname = ls_attr-name.
ls_fcat-datatype = ls_attr-type_name.
APPEND ls_fcat TO Et_fcat.
ENDLOOP.
cl_alv_table_create=>create_dynamic_table(
EXPORTING
it_fieldcatalog = Et_fcat
i_length_in_byte = abap_true
IMPORTING
ep_table = lo_table
EXCEPTIONS
generate_subpool_dir_full = 1
OTHERS = 2
).
IF sy-subrc <> 0.
* MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
* WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
" if node is multiple ( 0..n / 1..n ) return table type
IF io_node_info->is_multiple( ) EQ abap_true.
eo_data = lo_table.
ELSE.
FIELD-SYMBOLS: <lt_table> TYPE STANDARD TABLE.
ASSIGN lo_table->* TO <lt_table>.
IF <lt_table> IS ASSIGNED.
CREATE DATA eo_data LIKE LINE OF <lt_table>.
ENDIF.
" else, return the
ENDIF.
CATCH cx_root INTO lx_root.
ed_error_message = lx_root->get_text( ).
ENDTRY.
ENDMETHOD.
----------------------------------------------------------
GET_DATA( )
Parameters:
Parameter | Type | Ref To | Optional | Associated Type | Description |
---|---|---|---|---|---|
IO_NODE | Importing | Checked | IF_WD_CONTEXT_NODE | Node reference | |
ED_ERROR_MESSAGE | Exporting | STRING | Error message | ||
EO_DATA | Exporting | Checked | DATA | Data | |
ET_FCAT | Exporting | LVC_T_FCAT | Fields |
Logic:
METHOD GET_DATA .
DATA lv_count TYPE i.
DATA ls_fcat TYPE lvc_s_fcat.
DATA lv_index TYPE i.
DATA lv_attr_name TYPE string.
DATA lx_root TYPE REF TO cx_root.
FIELD-SYMBOLS: <lt_data> TYPE STANDARD TABLE,
<ls_data> TYPE any,
<lv_value> TYPE any.
TRY.
IF io_node IS NOT BOUND.
ed_error_message = 'Node reference cannot be empty'.
RETURN.
ENDIF.
" Get node data type and attribute list
wd_this->get_node_data_type(
EXPORTING
io_node_info = io_node->get_node_info( )
IMPORTING
eo_data = eo_data
et_fcat = et_fcat
ed_error_message = ed_error_message
).
" Return if any error or data type is not bound
IF ed_error_message IS NOT INITIAL OR
eo_data IS NOT BOUND.
RETURN.
ENDIF.
ASSIGN eo_data->* TO <lt_data>.
" get the no. of elements available in context node
lv_count = io_node->get_element_count( ).
" do for each element
DO lv_count TIMES.
" collect index value
lv_index = sy-index.
" Create a blank line and get the ref into <ls_dat>
APPEND INITIAL LINE TO <lt_data> ASSIGNING <ls_data>.
" return if line type is not assigned
IF <ls_data> IS NOT ASSIGNED.
RETURN.
ENDIF.
" Loop over each field/attribute and get the data
LOOP AT et_fcat INTO ls_fcat.
ASSIGN COMPONENT ls_fcat-fieldname
OF STRUCTURE <ls_data> TO <lv_value>.
IF <lv_value> IS ASSIGNED.
lv_attr_name = ls_fcat-fieldname.
io_node->get_attribute(
EXPORTING
index = lv_index
name = lv_attr_name
IMPORTING
value = <lv_value>
).
ENDIF.
ENDLOOP.
ENDDO.
CATCH cx_root INTO lx_root.
ed_error_message = lx_root->get_text( ).
ENDTRY.
ENDMETHOD.
----------------------------------------------------
Example:
Scenario: Let us say we need to read data from a node "NODE_DYN".
--------------------------
" Data declarations
DATA: lo_data TYPE REF TO data.
DATA lo_node TYPE REF TO if_wd_context_node.
FIELD-SYMBOLS: <lt_data> TYPE STANDARD TABLE.
" Get node information
wd_this->get_node_info(
EXPORTING
id_node_name = 'NODE_DYN'
* io_parent_node =
IMPORTING
* eo_node_info = LO_NODE_INFO
eo_node = lo_node
* ed_error_message =
).
" Get the data from context node
wd_this->get_data(
EXPORTING
io_node = lo_node
IMPORTING
eo_data = lo_data
* et_fcat =
* ed_error_message =
).
" assign data into dynamic table
ASSIGN lo_data->* to <lt_data>.
--------------------------
The internal table <lt_data> contains the data of our node "NODE_DYN"
For input attribute totally five input help mode could be selected. In most of time we would always like to leverage the existing dictionary search help defined in DDIC. However if existing one could not fulfill our requirement, we have to develop our own value help by ourselves.
I have used a simple example to demonstrate how to use "Freely Programmed" input help mode.
I have one consumer component ZCONSUMER, and one component ZUSER_HELP.
ZCONSUMER just have one input field for post ID and post description. When click value help of Post ID, the view of ZUSER_HELP will be opened and there is a SQL select to fetch the description according to post ID from database table.
1. in ZUSER_HELP, create the context node with attribute ID for post id, and description for post description. Since I use external mapping for data transfer from consumer component to value help provider component, so I mark the flag "Input Element(Ext.)". Define the node as interface node.
2. Implement the standard component interface IWD_VALUE_HELP. Redefine the method SET_VALUE_HELP_LISTENER. Also include your own value help view into the interface view WD_VALUE_HELP.
In the method SET_VALUE_HELP_LISTENER, I select the post description from database table and store it to attribute DESCRIPTION.
The listener reference is also stored into member variable of component controller for later usage.
method SET_VALUE_HELP_LISTENER . data: lv_id type socialdata-internal_id, lv_text type socialdata-socialposttext. wd_this->mr_listener = listener. data(lo_node) = wd_context->get_child_node( IF_COMPONENTCONTROLLER=>wdctx_post ). CHECK lo_node IS NOT INITIAL. lo_node->get_attribute( EXPORTING name = 'ID' IMPORTING value = lv_id ). SELECT SINGLE socialposttext INTO lv_text from socialdata where internal_id = lv_id. CHECK sy-subrc = 0. lo_node->set_attribute( name = 'DESCRIPTION' value = lv_text ). endmethod.
3. Draw a button in value help view to close the value help popup window once clicked. Just use the reference stored in step2 to close window.
method ONACTIONCLOSE .
wd_comp_controller->mr_listener->close_window( ).
endmethod.
4. in consumer component ZCONSUMER, create component usage to ZUSER_HELP, and create context node POST. Choose Input help mode Freely Programmed and choose component usage ZUSER_DEFINE_HELP from value help.
Create an interface controller usage on component usage ZUSER_DEFINE_HELP and finish the context node mapping, or else you will meet with runtime error
"External mapping of Node ZUSER_HELP#COMPONENTCONTROLLER.CONTEXT.POST is Not Completed yet".
Now once clicked the value help icon of input field Post ID, the value help window provided by component ZUSER_HELP will pop up automatically.
And once close button is clicked, the description field of consumer component will be filled.
I will use an example to demonstrate.The dynamically created elements are put into the red area below. Input the number of rows you want to dynamically generated and just create button to generate. Currently the content of text view is just filled with VALUE1,2,3,4... In next blog they will be filled with another approach by component usage cloning logic.
1. Create an empty group which acts as a container to hold all dynamically created ui elements.Specify layout as RowLayout.
2. Create an empty context node which also acts as a container for all dynamically created context node attributes.
3. In method WDDOMODIFYVIEW, just store the reference of view, which will be used later to manipulate UI elements after create button is clicked.
method WDDOMODIFYVIEW .
CHECK first_time = 'X'.
wd_this->mr_view = view.
endmethod.
4. create a new method in view controller.
In line 3 we get reference of place holder context node DYNAMIC. Then we get the node attributes by its node information object.
It is not necessary to create new attributes every time the create button is clicked unless the attribute has not really been created.
5. Implement the create button handler.
Make sure to delete all children of the UI place holder to avoid the repeated insertion of the ui elements with the same id, which will lead to runtime error. Then create new instance for label and text view, and specify their layout accordingly, so that each label will be put into a new line.
method ONACTIONCREATE . CONSTANTS: cv_label TYPE string VALUE 'LABEL', cv_field TYPE string VALUE 'FIELD', cv_bind_text TYPE string VALUE 'DYNAMIC.VALUE'. DATA: lv_count type i, lo_container type ref to cl_Wd_uielement_container. wd_context->get_attribute( EXPORTING name = 'NUMBER' IMPORTING value = lv_count ). CHECK lv_count > 0. create_context( lv_count ). DATA(lo_root) = wd_this->mr_view->get_element( 'DYNAMICUI' ). lo_container ?= lo_root. lo_container->remove_all_children( ). DO lv_count TIMES. data(lv_field_id) = cv_field && sy-index. data(lv_label_id) = cv_label && sy-index. data(lv_bind_path) = cv_bind_text && sy-index. DATA(lo_text_view) = cl_wd_text_view=>new_text_view( id = lv_field_id bind_text = lv_bind_path ). DATA(lo_label) = cl_wd_label=>new_label( id = lv_label_id label_for = lo_text_view->id text = lv_label_id ). CL_WD_ROW_HEAD_DATA=>new_row_head_data( element = lo_label ). cl_wd_row_data=>new_row_data( element = lo_text_view ). lo_container->add_child( the_child = lo_label ). lo_container->add_child( the_child = lo_text_view ). ENDDO. endmethod.
In NET311 the topic component usage clone is discussed there. One example is also given there:
I will reuse the component created in the blog Step by Step to create UI elements and context node attribute in the runtime . After I maintain the content number and click create button, the label and text view together with their bound context node attribute will be generated in the runtime. The value of text view "Echo from Usage clone:<number>" is returned by the cloned component usage.
1. Create a simple component ZDYNAMICUSAGE which will be consumed as component usage later. Implement the echo method in component controller.
2. In order to use component usage, there must be at least one static component usage.Also define usage of the interface controller in the consumer view controller.
3.In method CREATE_CONTEXT, just enhance one line. ( In the original example, I just set the value of newly-generated context attribute to its attribute name)
method CREATE_CONTEXT .
CONSTANTS: cv_value type string value 'VALUE'.
data(lo_node) = wd_context->get_child_node( 'DYNAMIC' ).
data(lo_node_info) = lo_node->get_node_info( ).
data(lt_attributes) = lo_node_info->get_attributes( ).
DO iv_count TIMES.
DATA(lv_attribute_name) = cv_value && sy-index.
READ TABLE lt_attributes WITH KEY name = lv_attribute_name TRANSPORTING NO FIELDS.
IF sy-subrc <> 0.
data(ls_attribute_prop) = VALUE wdr_context_attribute_info( NAME = lv_attribute_name
TYPE_NAME = 'STRING' ).
lo_node_info->add_attribute( attribute_info = ls_attribute_prop ).
DATA(lv_value) = wd_this->get_value_by_index( sy-index ).
lo_node->set_attribute( name = lv_attribute_name value = lv_value ).
ENDIF.
ENDDO.
endmethod.
4. Define one attribute in view controller, which is an internal table to store all references of component usage instance.
In view controller WDDOINT, insert the static component usage to the internal table. The internal table would have the first line as static component usage instance and all remaining ones for cloned component usage from the static one.
method WDDOINIT .
DATA(lo_static_usage) = wd_this->wd_cpuse_zclone_example( ).
APPEND lo_static_usage TO wd_this->gt_cmp_usages.
endmethod.
5. Implement the method get_value_by_index which is called in step3. I will read the internal table gt_cmp_usages by index. Index 1 means this is a static component usage so I directly use the one return from wd_this->wd_cpuse_zclone_example( ). Or else the left one will be cloned from the static one. Since the usage name should be unique, so I use a prefix and an index to fulfill the uniqueness.
method GET_VALUE_BY_INDEX . DATA(lo_static_com_usage) = wd_this->wd_cpuse_zclone_example( ). DATA: lo_generic_usage TYPE REF TO if_wd_component_usage, lo_interface_control TYPE REF TO ZIWCI_DYNAMICUSAGE. READ TABLE wd_this->gt_cmp_usages ASSIGNING FIELD-SYMBOL(<usage>) INDEX iv_index. CASE iv_index. WHEN 1. IF lo_static_com_usage->has_active_component( ) IS INITIAL. lo_static_com_usage->create_component( ). ENDIF. lo_generic_usage = lo_static_com_usage. WHEN OTHERS. READ TABLE wd_this->gt_cmp_usages ASSIGNING FIELD-SYMBOL(<dyn_usage>) INDEX iv_index. IF sy-subrc <> 0. DATA(lv_usage_name) = 'DYNAMIC_USAGE' && sy-index. data(lo_dyn_usage) = lo_static_com_usage->create_comp_usage_of_same_type( name = lv_usage_name ). APPEND lo_dyn_usage TO wd_this->gt_cmp_usages. ENDIF. IF lo_dyn_usage->has_active_component( ) IS INITIAL. lo_dyn_usage->create_component( ). ENDIF. lo_generic_usage = lo_dyn_usage. ENDCASE. lo_interface_control ?= lo_generic_usage->get_interface_controller( ). rv_output = lo_interface_control->get_field_value( iv_index ). endmethod.
In the debugger I would observe that every component usage in gt_cmp_usages are unique:
If the component usage is not defined at design time, it is not possible to embed an interface view of this component usage into a ViewUIElementContainer of another view. It is also not possible to define a navigation link connecting any outbound plug of an existing view to an inbound plug of this interface view at design time. In this case methods of the Web Dynpro API have to be applied.
I will use the example in the following two blogs to demonstrate the trick.
1. Step by Step to create UI elements and context node attribute in the runtime
2. Step by step to use Component usage clone
after you specify the number of rows you want to generate and click the create button, all ui elements and context node attribute will be generated in the runtime. The ui elements marked in blue come from the interface view of another compoonent, and this view embedding logic is also done dynamically in the runtime.
1. Draw a simple caption in component ZDYNAMICUSAGE which will be consumed by host component ZDYNAMIC.
2. The layout of main view in component ZDYNAMIC remains unchanged.
Create an outbound plug, which will be used in API later.
Create a new attribute in view controller to store all component usage name, both static one and the dynamical one cloned from the static one.
DATA(lo_static_com_usage) = wd_this->wd_cpuse_zclone_example( ).
DATA: lo_generic_usage TYPE REF TO if_wd_component_usage,
lo_interface_control TYPE REF TO ZIWCI_DYNAMICUSAGE.
READ TABLE wd_this->gt_cmp_usages ASSIGNING FIELD-SYMBOL(<usage>) INDEX iv_index.
CASE iv_index.
WHEN 1.
IF lo_static_com_usage->has_active_component( ) IS INITIAL.
lo_static_com_usage->create_component( ).
ENDIF.
APPEND 'ZCLONE_EXAMPLE' TO wd_this->gt_usage_name.
lo_generic_usage = lo_static_com_usage.
WHEN OTHERS.
READ TABLE wd_this->gt_cmp_usages ASSIGNING FIELD-SYMBOL(<dyn_usage>) INDEX iv_index.
IF sy-subrc <> 0.
DATA(lv_usage_name) = 'DYNAMIC_USAGE' && sy-index.
data(lo_dyn_usage) = lo_static_com_usage->create_comp_usage_of_same_type( name = lv_usage_name ).
APPEND lo_dyn_usage TO wd_this->gt_cmp_usages.
APPEND lv_usage_name TO wd_this->gt_usage_name.
ENDIF.
IF lo_dyn_usage->has_active_component( ) IS INITIAL.
lo_dyn_usage->create_component( ).
ENDIF.
lo_generic_usage = lo_dyn_usage.
ENDCASE.
lo_interface_control ?= lo_generic_usage->get_interface_controller( ).
rv_output = lo_interface_control->get_field_value( iv_index ).
endmethod.
4. In method ONACTIONCREATE, now also create seperate view container UIElement instance for each component usage. That view container will be used to embed
the interface view exposed by component ZDYNAMICUSAGE. Then we use API prepare_dynamic_navigation to create a navigation link dynamically, from host view in component ZDYNAMIC to the interface view of component ZDYNAMICUSAGE. The component usage name stored in attribute gt_usage_name in step3 will be used during API call. Finally fire the outbound plug of MAIN view to make the embedded view displayed in UI.
method ONACTIONCREATE .
CONSTANTS: cv_label TYPE string VALUE 'LABEL',
cv_field TYPE string VALUE 'FIELD',
cv_container TYPE string VALUE 'EMBEDDED',
cv_bind_text TYPE string VALUE 'DYNAMIC.VALUE'.
DATA: lv_count type i,
lo_container type ref to cl_Wd_uielement_container.
wd_context->get_attribute( EXPORTING name = 'NUMBER' IMPORTING value = lv_count ).
CHECK lv_count > 0.
create_context( lv_count ).
DATA(lo_root) = wd_this->mr_view->get_element( 'DYNAMICUI' ).
lo_container ?= lo_root.
lo_container->remove_all_children( ).
DO lv_count TIMES.
data(lv_field_id) = cv_field && sy-index.
data(lv_label_id) = cv_label && sy-index.
data(lv_bind_path) = cv_bind_text && sy-index.
DATA(lo_text_view) = cl_wd_text_view=>new_text_view( id = lv_field_id bind_text = lv_bind_path ).
DATA(lo_label) = cl_wd_label=>new_label( id = lv_label_id label_for = lo_text_view->id text = lv_label_id ).
CL_WD_ROW_HEAD_DATA=>new_row_head_data( element = lo_label ).
cl_wd_row_data=>new_row_data( element = lo_text_view ).
DATA(lv_container_id) = cv_container && sy-index.
data(lo_view_cont) = CL_WD_VIEW_CONTAINER_UIELEMENT=>new_view_container_uielement( id = lv_container_id ).
CL_WD_ROW_HEAD_DATA=>new_row_head_data( element = lo_view_cont ).
lo_container->add_child( the_child = lo_label ).
lo_container->add_child( the_child = lo_text_view ).
lo_container->add_child( the_child = lo_view_cont ).
ENDDO.
DATA: lr_api_main_view TYPE REF TO if_wD_view_controller.
lr_api_main_view = wd_this->wd_get_api( ).
DO lv_count TIMES.
READ TABLE wd_this->gt_usage_name ASSIGNING FIELD-SYMBOL(<usage_name>) INDEX sy-index.
DATA(lv_position) = 'MAIN/' && cv_container && sy-index.
lr_api_main_view->prepare_dynamic_navigation(
source_window_name = 'ZDYNAMIC'
source_vusage_name = 'MAIN_USAGE_0'
source_plug_name = 'VIEW_TO_USAGE'
target_component_name = 'ZDYNAMICUSAGE'
target_component_usage = <usage_name>
target_view_name = 'ZDYNAMICUSAGE'
target_plug_name = 'DEFAULT'
target_embedding_position = lv_position ).
wd_this->fire_view_to_usage_plg( ).
ENDDO.
endmethod.
How to find the value of source_vusage_name?
Hi,
I got a requirement where i need to read the filtered values from ALV table in webdynpro ABAP. Some workaround helped me to make my task easier.Below is the code which i used to read the filtered values.
DATA: lr_interfacecontroller TYPE REF TO iwci_salv_wd_table.
DATA: l_value TYPE if_salv_wd_table=>s_type_param_get_ui_info.
DATA: lt_salv_bs_t_int TYPE salv_bs_t_int.
DATA: ls_salv_bs_t_int TYPE i.
DATA: l_displayed_element TYPE LINE OF if_salv_wd_table=>s_type_param_get_ui_info-t_displayed_elements.
DATA: lt_visible_indices TYPE cl_wdha_assist=>indices.
DATA: lw_visible_indices LIKE LINE OF lt_visible_indices.
TRY.
lr_interfacecontroller = wd_this->wd_cpifc_used_component( )." ( In my case : lr_interfacecontroller = wd_this->wd_cpifc_source_roles_dirclty( ).
CATCH cx_wdr_rt_exception.
ENDTRY.
IF NOT lr_interfacecontroller IS INITIAL.
l_value = lr_interfacecontroller->get_ui_info( ). " ( GET_UI_INFO( ) : The method returns information about the currently displayed ALV.)
IF l_value-s_service_info-is_filtered = abap_true. "( To check if filter is applied)
lt_salv_bs_t_int = l_value-t_displayed_elements.
CLEAR lt_visible_indices[].
LOOP AT l_value-t_displayed_elements INTO l_displayed_element.
l_index-index = l_displayed_element.
APPEND l_index TO lt_visible_indices. " ( Returns the index(s) of the internal table records which we have selected from filtered values)
ENDLOOP.
SORT lt_visible_indices BY index.
ENDIF.
ENDIF.
Hope this helps for all who have similar requirement which makes their task easier.
Comments/Suggestions are welcome.
Thanks
Katrice Hawkins
You can use tcode WD_TRACE_TOOL to switch on trace.
After that when you launch your webdynpro application, you can observe there is a Webdynpro trace window embedded in the bottom of the application. You can either deactivate the trace in old dynpro tool or in that embedded window.
After you click Store trace as Zip File & Finish trace,you can save the trace file as zip locally.
The trace setting is checked and loaded in the very beginning phase of webdynpro runtime initialization,
The trace is actually added in the runtime via the utility macro below:
And finally into trace file with xml format
Under package SWDP_PERFORMANCE_VERIFICATION there is a pair of reports WDT_TRACE_ON and WDT_TRACE_OFF which could switch on and switch off performance trace.
To switch on trace, set the user parameter WDA_PERF_TRACE_ON as abap_true, then run report WDT_TRACE_ON.
In the webdynpro runtime framework code,you could see there is code to record the runtime performance information implemented via keyword GET RUN TIME FIELD.
You can find all positions where framework has done such performance recording with the help of report RS_ABAP_SOURCE_SCAN with search keyword name = macro name wdr_perf_trace_on and search package name = SWDP_RUNTIME_CORE.
Once you activate the performance trace, you can run your application in UI as usual. After application runs over, you can deactivate the trace by running report WDT_TRACE_OFF, it will retrieve all runtime performance trace information with start and stop time.
the report will also do some calculations based on those two times and display the result:
For description of each columns, please refer to description maintained in DDIC structure STRC_S_STAT.
Since recently when I am supporting local customers I am frequently asked by question like "Which version of Internet explorer is supported in NW7XX for ABAP webdynpro / BSP?" and "is firefox also supported?",
I just write this step by step guide how to figure it out.
1. openhttp://service.sap.com, then click hyperlink "Product availability"
2. Now Product Availability Matrix is opened. Choose the product you want to query under "Available as of Q4/2013 or Q1/2014", for example SAP NETWEAVER 7.4
3. click tab "Technical Release Information"->"Web Browser Platforms". If we need to check web browsers against ABAP webdynpro and BSP, we just need to choose
"Application Server ABAP" for Product Instance. You can set filter for Firebox, Chrome and IE accordingly.
Hi,
Following are the new layout's in SAP NetWeaver 7.40.
1) Form Layout
2) Matrix Layout
3) Row Layout
4) Flow Layout
5) Formlayout Advance
6) FormDesign Layout
7) Grid Layout
8) Raster Layout
Commets/Suggestions/Opinions/Detailed Explanations are welcome.
Thanks
Katrice