Exercise UI CRM2006S Part3
Exercise UI CRM2006S Part3
Exercise UI CRM2006S Part3
You have the task to identify and inspect existing BOL Objects.
1-A Take a look at the definition of BOL objects and relationships in Customizing
Which attribute structure is used
… for the order header (BTOrder)?
… for the business partner header (BuilHeader)?
What is/are the relationship name(s)
… to navigate from the business partner root object (BuilHeader) to the dependent object
BuilStandardAddress
… to navigate from the business transactions root object (BTOrder) to the dependent
object BTCustomerH
1-B What is the GenIL implementation class
… of the business partner?
… of the Business Transaction?
1-C Check the search objects in the BOL Browser
Compare the functionality of search and dynamic search objects
BTQuery1O
BTQ1Order
What will be the result objects of the query
Check the relations for BuilHeader, which one could lead to the Standard Address?
…..
Check the relations for BTOrder, how do you get to the customer enhancement data?
Solution 2
Double click on variable messages to see the list of messages coming from the standard Order
APIs.
1 Create a new UI component with name Z##H (where ## is your participant number).
2 Create a new view
a. Choose type “empty view”
b. Bind the context node to model node BTAdminH
3 Manipulate the placement of the fields by using the config tool
2 Create a view (for display purposes, e.g. for including it into an overview page).
a. Go to “Browser Application Structure” (top left)
b. Right click on on “Views” in the left of the screen and click “Create” (now a wizard
should come up)
i. Start: This is just for your information, click continue
ii. Define Name: Type in the name of your View (your typing is case
sensitive). Training proposal naming: “DetailsOV”
iii. Add Model Node: Choose the BOL entity BTAdminH by using the F4 and
selecting the entry BTAdminH. Put in a name in the field
“Model Nodes” to give the context node a name (Advice:
name it the same as in the BOL for identification and
maintainability reasons)
iv. Add Value Node: This is only needed if you want to add fields which can not
be retrieved from the BOL (advanced). At this point in
time leave it blank and click continue.
v. Add Model Attr: Skip this section as the attributes are automatically
retrieved by the BOL model.
vi. Add Value Attr: Adding these value attributes coheres with the value node.
Again, skip this step by clicking continue without entering
data.
vii. Links to CuCo: This step is used for binding context nodes. Again skip this
step as there is no context node available for binding.
viii. View Type: Select the view type “Empty View”
ix. Complete: Here you get an overview of your inputs. Click complete to
trigger the generation of the view.
4 Go to the Runtime Repository editor in edit mode and assign a component set to the
model. If you do not know which one to take, take ALL (you should choose a
component set which suits your needs. This means that the component must also
include the BOL component of which you intend to use objects from.
5 Double click on your view again and notice the configuration tab appears on the right
(if the configuration tab does not appear, please leave the workbench and enter your
new component again)
6 In order to test your view go to the runtime repository. Click the pencil to switch to edit
mode. Open the window (click on the arrow) and assign the view to the window by
right-clicking and adding the view. After saving the changes you can click “Test” in the
left top and check if the fields are aligned correctly (don’t worry about the content of
the fields at this point in time). Alternatively you can use “F8” to start the test mode.
After testing remove the view from the window (again click edit, remove the view and
save your changes).
Exercise 4
Solution 4
1 Create a second view for editing purposes. The goal is to navigate from your first view
(which is read-only) to this second view which will enable the user to change data.
Training proposal naming for this second view: “DetailsEF”
a. Remark: The view should be the same as the first view (fields and their alignment)
with the exception that it will only be used for editing. However, making the view
editable will be handled in a later exercise.
b. Choose View type empty View
2 Create a button with an event on your first view
3 Implement the eventhandling of the button of the first view
4 As a reaction to the click of the button implement the navigation to the second view
5 Create a back button on the second view
6 Implement the eventhandling of the back button
7 As a reaction to the click of the back button implement the navigation back to the first
view
Solution 5
1 See Solution of exercise 3 if you get stuck with the creation of the second view.
CRM WebClient 5.1 Workshop Page 13
a. You have to adjust the .htm coding due to the fact that the view is now not embedded
in an overview page but is a standalone view. Following you find the complete .htm
coding (figure out the delta as a practice)
<%@page language="abap" %>
<%@extension name="thtmlb" prefix="thtmlb" %>
<%@extension name="chtmlb" prefix="chtmlb" %>
<%
DATA:lv_xml type string.
lv_xml = controller->CONFIGURATION_DESCR->GET_CONFIG_DATA( ).
%>
<chtmlb:config xml = "<%= lv_xml %>"
mode = "RUNTIME" />
b. Remark: As this view will be the equivalent to the first view, take into consideration
that you might want to have the same fields on the view
IF gt_button IS INITIAL.
ls_button-type = cl_thtmlb_util=>gc_icon_edit.
ls_button-enabled = abap_true.
ls_button-on_click = 'EDIT'. "#EC NOTEXT
APPEND ls_button TO gt_button.
ENDIF.
Go to edit of your *.htm file and add these lines as the first thtmlb lines, but below the
ABAP scripting:
<%@page language="abap"%>
<%@extension name="thtmlb" prefix="thtmlb" %>
<%@extension name="chtmlb" prefix="chtmlb" %>
<thtmlb:toolbar id = "HeaderToolbar"
buttons = "<%= controller->gt_button %>"
maxButtonNumber = "3"
foreignUse = "TRUE" />
<chtmlb:overviewFormConfig/>
3 To create the event handler right click on the “Event Handler” and create your event
handler by just entering a meaningful name e.g.‘EDIT’.
Remark: The wizard will create the eventhandler automatically. This includes the
generation of a prefix “EH_ON” which will be put in front of the name you enter. Also
the eventhandler is case sensitive which means you need to enter the same string as you
have defined the on-click parameter of the button in the method
DO_PREPARE_OUTPUT.
* when activating Impl Class, error message ‘do_handle_event is already redefined’
comes up. Just click on the method name and press redefine button.
4 Implement the navigation from ‘DetailsOV’ to the second view ‘DetailsEF’
a. Create an outbound plug (by right clicking and using the wizard) for DetailsOV and
choose a name which indicates where the navigation is going to (e.g.
TODETAILSEF).
e. View DetailsOV: Go to the outbound plug you have created and call the navigational
link by using the following coding.
Remark: This coding assumes that the Navigational Link is named ToDetailsEF.
view_manager->navigate( source_rep_view = rep_view
outbound_plug = 'ToDetailsEF' ).
* Back button
ls_button-type = cl_thtmlb_util=>GC_ICON_PREVIOUS.
ls_button-text = cl_wd_utilities=>get_otr_text_by_alias( 'CRM_UIU_BT/BACK' ).
ls_button-on_click = 'BACK'.
ls_button-page_id = me->component_id.
ls_button-enabled = abap_true.
APPEND ls_button TO rt_buttons.
CLEAR ls_button.
7 Implement the navigation from Details EF back to the first view DetailsOV
(respectively the overview page)
a. Create an outbound plug for the second view DetailsEF (by right clicking and using
the wizard) and choose a name which indicates where the navigation is going to (e.g.
TODETAILSOV).
b. Create an inbound plug for the read only view DetailsOV and choose a name which
indicates where the navigation is coming from (e.g. FROMDETAILSEF).
c. Create a navigational link to link the two views for the back navigation
i. Go to the runtime repository editor
ii. Click the pencil in order to go to the edit mode
iii. Right click on “Navigational Links” to create a navigational link
1. Define a Name (Advice: use one string with capital letters for each
word, e.g. “FromDetailsEF”)
2. Choose a source (e.g. DetailsEF)
3. Choose the outbound plug to (e.g. TODETAILSOV)
4. Choose the target view (e.g. OverviewPage)
5. Choose the inbound plug of the target view
(e.g. FROMDETAILSEF).
8 View DetailsEF: Go to the event handler you have created and call the outbound plug.
Remark: This coding assumes that you named the outboundplug
“OP_TODETAILSOV”.
op_todetailsov( ).
View Details EF: Go to the outbound plug you have created and call the navigational
link by using the following coding.
Remark: This coding assumes that the Navigational Link is named ‘FromDetailsEF’.
view_manager->navigate( source_rep_view = rep_view
outbound_plug = 'FromDetailsEF' ).
Solution 6
1 Go to the Browser Application Structure and right click on Custom Controllers to start
the wizard for custom controller generation
a. Enter a name HeaderCuCo
b. Create a node BTAdminH and choose the BOL entity BTAdminH. Complete the
wizard without making any further changes
2 Go to your read-only view
a. Navigate into the CTXT class
b. Open the create method for the context node you want to bind to the custom
controller and enter the following coding.
* bind to custom controller
owner->do_context_node_binding(
Remark: This coding assumes, that your CustomController and Context Nodes are named
as proposed above under 1. Also replace ### with your number.
Exercise 7
1 Create a new UI component Z###S to create a search (remember to save all objects as
a local object, package $TMP or use the package that is provided by the trainer)
2 Create a custom controller which will be used to connect search and search result.
Hint: One context node must be created. This context node is used by both views, the
search and search result.
3 Create a view for the search
4 Create a view for the search result
5 Create a viewset with 1 column and 2 rows in which the search is in the first row and
the search result is in the second row
6 Put the various parts together (views into viewset, ensure binding and therefore
proper data display) and make the viewset available at runtime.
7 Hint: To make it work you have to adjust the htm files. Try to find existing SAP
standard components where you can use the coding from.
8 Implement the hyperlink for the field Description
Attention; If you have use other search objects (e.g. BTQOpp and BTQROpp,
then you have to look into table CRMC_ORLSTA_BTIL (for one order
objects) in order to find out which objects are related to the SearchResult. Use
the found object instead of the BTOrder object
For none 1Order objects you have to check the method GET_MODEL of the
implementing class of the BOL component. You can find this in IMG in the
basic settings of the GenIL Customizing
d. Choose Type Table View
e. Complete the wizard
7 Put the views and the viewset together and make it available at runtime
a. Go to the Runtime Repository Editor and go to edit mode
b. Enable the display of the ViewSet at runtime by right clicking on the MainWindow
and adding the ViewSet
CRM WebClient 5.1 Workshop Page 20
c. Still in the Runtime Repository Editor Open the ViewSet and assign the search and
search result view to the according view areas
Remark: The assumption is that you created an object in the 1-Order environment.
Also the assumption is that you named the context node for the search “Query”. If
you named it differently then you have to adjust your .htm coding.
d. Now you can do the configuration for the search view
e. Adjust the search result view
i. Replace the htm coding of the search result view by the following code
<%@page language="abap" %>
<%@extension name="chtmlb" prefix="chtmlb" %>
<%
data: lv_xml type string.
lv_xml = controller->CONFIGURATION_DESCR->GET_CONFIG_DATA( ).
%>
<chtmlb:tableExtension tableId = "ResultList"
layout = "FIXED" />
<chtmlb:configTable xml = "<%= lv_xml %>"
id = "ResTable"
navigationMode = "BYPAGE"
onRowSelection = "select"
table = "//Result/Table"
width = "100%"
headerVisible = "FALSE"
hasLeadSelection = "TRUE"
visibleRowCount ="10"
actionsMaxInRow = "5"
ii.
Remark: This coding assumes that the name of your search result context
node is “Result”
iii. Now you can do the configuration for the search result view
f. Adjust the Viewset
i. Replace the htm coding of the ViewSet
Remark: It is assumed that the viewarea in which you have placed the
search view is named “Search” and that the viewarea in which you have
placed the search result view is named “Result”.
<%@page language="abap"%>
<%@ extension name="bsp" prefix="bsp"%>
<%@extension name="thtmlb" prefix="thtmlb" %>
<%@extension name="chtmlb" prefix="chtmlb" %>
<chtmlb:pageType type="SEARCH">
<thtmlb:searchResultFrame>
<bsp:call comp_id = "<%= controller->GET_VIEWAREA_CONTENT_ID( 'Result' ) %>"
url = "<%= controller->GET_VIEWAREA_CONTENT_URL( 'Result' ) %>" />
</thtmlb:searchResultFrame>
</thtmlb:searchFrame>
</chtmlb:pageType>
g. Create an event handler on search page to react to the click on the search button.
Name it as the onEnter event in the search.htm is named, e.g. “SEARCH”. In the
event handler, put the following coding (adjust it by your context node if
necessary):
DATA:
lr_qs TYPE REF TO cl_crm_bol_dquery_service,
lr_qr TYPE REF TO if_bol_bo_col,
lr_msg_srv TYPE REF TO cl_bsp_wd_message_service.
lr_qs ?= me->typed_context->query->collection_wrapper->get_current( ).
lr_qr = lr_qs->get_query_result( ).
me->typed_context->result->set_collection( lr_qr ).
Exercise 8
1 Implement navigation for your hyperlink for the Description so it navigates to your
Z###H component, showing the overview page
2 Optional: Implement Hyperlink for Object ID and display transaction in different
component. (Navigation via L-Shape)
Solution 8
lr_window = me->view_manager->get_window_controller( ).
lr_window->call_outbound_plug( 'SINGLESELECTION' ).
ENDMETHOD.
iii. Create Inbound plug IP_DEFAULT for the Window controller class. Use
Wizzard, enter DEFAULT as name of the plug ( will be concatenated by
wizard. Leave created method empty.
iv. Define the component interface in the Runtime Repository editor
1. Press Icon ‘Change’
2. Open ‘Component Interface’ node. Set Cursor on ‘Interface
Controller’ and press right mouseclick to create context. Press right
mouseclick again to create ‘Model Node’. Choose context node
CASE iv_usage->usage_name.
* Search
WHEN 'Z##Search'.
CALL METHOD lv_usage->bind_context_node
EXPORTING
* header
WHEN 'Z##Header'.
CALL METHOD lv_usage->bind_context_node
EXPORTING
iv_controller_type = cl_bsp_wd_controller=>co_type_component
iv_target_node_name = 'BTORDER'
iv_node_2_bind = 'BTORDER'.
WHEN OTHERS.
ENDCASE.
Define the navigational link with the name according to the string you have put in the
event handler in the search component, e.g. SINGLESELECTION
3. as source define the component usage for the search
4. As target define the component usage of the header (h-component)
5. This will handle the connection from the search to the header
CASE iv_property.
WHEN if_bsp_wd_model_setter_getter=>fp_fieldtype.
rv_value = cl_bsp_dlc_view_descriptor=>field_type_event_link.
WHEN if_bsp_wd_model_setter_getter=>fp_onclick.
rv_value = 'DISPLAY'. "#EC NOTEXT
WHEN if_bsp_wd_model_setter_getter=>fp_tooltip.
ENDCASE.
d. Create an eventhandler with the same name as in the onclick event of the hyperlink
e.g. EH_ONDISPLAY . Copy and adapt the coding that you have inserted in the
event handler EH_ONSINGLESELECT in the former exercise. Change the name
lr_entity ?= me->typed_context->btorder->collection_wrapper->get_current( ).
IF lr_entity IS NOT BOUND OR
lr_entity->alive( ) EQ abap_false.
ELSE.
CREATE OBJECT lr_col TYPE cl_crm_bol_bo_col.
CHECK lr_col IS BOUND.
lr_col->add( lr_entity ).
* call outbound plug
op_todisplay( lr_col ).
ENDIF.
lr_window = me->view_manager->get_window_controller( ).
lr_window->call_outbound_plug( iv_outbound_plug = 'NAVIGATE_DISPLAY'
iv_data_collection = iv_data_collection ).
endmethod.
iii. In the component Usage for the search component add the outbound plug
NAVIGATE_DISPLAY. Choose context menu, select ‘Delegate to window
outbound Plug’, choose NAVIGATE_DISPLAY as outbound Plug of higher
window.
Exercise 9
1 Implement the input readiness of the editable (second) view you have created
Solution 9
1 Go to the eventhandler of the first view (DetailsOV) and add the following lines in
front of the call of the outbound plug.
Remark: With this coding it is assumed that you named your context node
BTAdminH. The locking has to be performed in order to be able to edit the view.
DATA: lr_entity TYPE REF TO cl_crm_bol_entity.
* After locking, a given entity must be set again as current via find.
IF lr_entity->alive( ) = abap_true.
me->typed_context->btadminh->collection_wrapper->find( iv_bo = lr_entity ).
ENDIF.
ENDIF.
If you still encounter difficulties set a breakpoint in the I-Getter method of an attribute
in the editable view and check the return value.
Exercise 10
Solution 10
Exercise 11
1 Enhance BOL entity BTCustomer_H with an attribute with name “Field##”. This step
will be provided by the trainer
2 Make the relevant enhancement to bring the new field to the UI
Solution 11
The enhancement set is a logical group for your enhancements, you can enhance
different UI components in one enhancement set.
.ii Still in transaction SM30, enter Table/View name BSPWDV_EHSET_ASG
and activate your enhancement set for your Client
.ii Enter name of standard component BT111H_OPPT and the name of your
enhancement set Z_###_EHSET and Press ‘Display’.
.iii Press Button ‘Enhance Component’
.vi Confirm or choose the name for the repository File (.xml)
Choose Package (will be given by instructor) for your enhancement and select
transport requests if required).
Remark: Wizard generates entry in customizing table BSPWD_COMP_EXT.
.c Edit Enhancement (Component Workbench)
.i Choose the View DetailsOV that you want to enhance, choose context menu,
press ‘Enhance’
Additionally, a new _IMPL class and a new _CTXT class will be generated by the
wizard ( as you already might know these steps from the Context Node
enhancement Wizard in CRM 5.0)
.ii Create new Context node for Customer enhancement
Exercise 12
Solution 12
CASE iv_usage->usage_name.
WHEN 'Search'. "#EC NOTEXT
TRY.
wccontext = iv_usage->get_context_node( 'WORKCENTERINF' ).
wccontext->set_s_struct( attribute_path = '' component = 'COMPONENT' value = 'Z
###_WCC' ) ."#EC NOTEXT
wccontext->set_s_struct( attribute_path = '' component = 'INTERFACE_VIEW' value
= 'MainWindow' ) ."#EC NOTEXT
wccontext->set_s_struct( attribute_path = '' component = 'GROUP_TYPE' value = 'B
B' ) ."#EC NOTEXT
CATCH cx_root.
ENDTRY.
ENDCASE.
CATCH cx_root.
ENDTRY.
CATCH cx_root.
ENDTRY.