Skip to Content
Author's profile photo Jerry Wang

An example of End to End extension on CRM Fiori application – part3

In previous blogs:

I introduced how to create a new extension field on Opportunity OData model, expose it via OData service and consume it in Fiori UI.

Aim of this blog

In this blog we will go a step further: we will allow end user to manually type some value in this extension field and persist the value to the database table in CRM backend server, when save button is clicked.

Requirement: The value must be saved into a new corresponding field in database table CRMD_OPPORT_H.

Here below is the UI so far we get:

  • There is an extension field done on Opportunity detail view.
  • When the detail is rendered, the value of the extension field is fetched from database table CRMD_ORDERADM_H, field CREATED_BY.


Step1 create new field in Opportunity edit view

We notice that once edit button in toolbar is clicked, we will reach opportunity edit view. Now the extension field is only available in detail view ( read only there ), so we need also to add the extension field into edit view.

Use the similar approach in part2 blog to bring the extension field to edit view. Currently we didn’t do any binding to this field in edit value, just use a hard code value “Jerry”

<core:FragmentDefinition xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:ui="sap.ui.layout">
   <ui:form.SimpleForm id="OpportunityEditExtension" minWidth="1024" maxContainerCols="2" editable="true" layout="ResponsiveGridLayout"
    labelSpanL="3" labelSpanM="3" emptySpanL="4" emptySpanM="4" columnsL="1" columnsM="1" class="editableForm" >
         <Label id="opportunityCreatedByLbael" text="Created By">
         <Input id="createdByInput" value="Jerry"></Input>

After this step the edit UI looks like below:


Step2 Enhance controller JavaScript code to also send the value of extension field to backend

Check the extension-point we could use to put the extension field value to the request sent to backend via searching keyword “”extHook”:


Implement the extension-point by creating a new controller extension and paste the following source code:

sap.ui.controller("cus.crm.opportunity.CRM_OPPRTNTYExtension.view.extS4", {
    onInit : function () {
        //Execute onInit for the base class BaseMasterController;
extHookAddCustomHeaderFields : function(oEntry) {
//  "createdByInput" is the id for extension UI element defined in extS4CreatedBy.fragment.xml
        var oExtensionControl = this.byId("createdByInput");
//  get the current value that end user has entered in extension field in detail view
        var extensionValue = oExtensionControl.getValue();
        oEntry.extCreatedBy = extensionValue;

Now we could test in Edit UI. Once you type something in Created By field and click save button, you should see your input is successfully passed to backend via http post operation. Of course so far it will not take effect since the backend support for this extension field is not done yet. We will finish it in next step.


Step3 enhance OData service implementation so that extension field could be persisted in database table

First we have to identify which method in the backend needs to be enhanced. Set a breakpoint on OData service provider class: method PATCH_ENTITY and click save button, breakpoint is triggered:


The user input in Fiori UI is already successfully passed to backend by gateway framework. Now it is our turn to pass it to one order related function module to persist it into database table.


as a result, redefine method /IWBEP/IF_MGW_APPL_SRV_RUNTIME~PATCH_ENTITY in your own DPC_EXT class.

In this method, the idea is, to store the extension value passed from Fiori UI via gateway framework ( the field CRMT_ODATA_OPPT_HEADER-EXT_CREATED_BY ) to Opportunity service implementation’s internal buffer maintained in CL_CRM_OPPORTUNITY_IMPL=>GT_OPPORT_H ( which is an internal table with line structure CRMT_OPPORT_H_COM. And we need also to create a new field in database table CRMD_OPPORT_H to persist the value. To summarize, we need two new extension fields besides the one created in the first blog.

You can manually create them separately, or use some extension tool like EEW or AET ( application extension tool ).

You may look at these two wikis regarding extension field creation approach in CRM:

In this blog, I use AET so the field name is automatically determined by the tool: FLD00008B.

The final source code of patch_entity:

METHOD /iwbep/if_mgw_appl_srv_runtime~patch_entity.
    CALL METHOD super->/iwbep/if_mgw_appl_srv_runtime~patch_entity
        iv_entity_name          = iv_entity_name
        iv_entity_set_name      = iv_entity_set_name
        iv_source_name          = iv_source_name
        io_data_provider        = io_data_provider
        it_key_tab              = it_key_tab
        it_navigation_path      = it_navigation_path
        io_tech_request_context = io_tech_request_context
        er_entity               = er_entity.
    FIELD-SYMBOLS: <header_from_ui> TYPE crmt_odata_oppt_header,
                   <header_buffer>  TYPE crmt_opport_h_com,
                   <value_ui>       TYPE crmt_odata_oppt_header-ext_created_by,
                   <value_db>       TYPE crmt_opport_h_com-fld00008b,
                   <input_fields>   LIKE LINE OF cl_crm_opportunity_impl=>gt_input_fields.
    DATA: ls_input TYPE crmt_input_field_names.
    CHECK iv_entity_name = 'Opportunity'.
    ASSIGN er_entity->* TO <header_from_ui>.
    CHECK sy-subrc = 0.
    READ TABLE cl_crm_opportunity_impl=>gt_opport_h ASSIGNING <header_buffer> INDEX 1.
    CHECK sy-subrc = 0.
    ASSIGN COMPONENT 'EXT_CREATED_BY' OF STRUCTURE <header_from_ui> TO <value_ui>.
    CHECK sy-subrc = 0.
    ASSIGN COMPONENT 'FLD00008B' OF STRUCTURE <header_buffer> TO <value_db>.
    CHECK sy-subrc = 0.
    <value_db> = <value_ui>.
    READ TABLE cl_crm_opportunity_impl=>gt_input_fields ASSIGNING <input_fields>
     WITH KEY objectname = 'OPPORT_H'.
    CHECK sy-subrc = 0.
*   Notify One order function module that we want to persist the value of this field
    ls_input-fieldname = 'FLD00008B'.
    INSERT ls_input INTO TABLE <input_fields>-field_names.

Now we could test the save operation on this extension field:


Once we click save button, the value is persisted to database table as expected.


Step4 adapt the read operation implementation to load the extension field value from DB table

This step is quite simple, just make small adaptions in private method FILL_CREATED_BY

Before: ( in blog 2 )

DATA: lv_created_by TYPE crmd_orderadm_h-created_by.
SELECT SINGLE created_by INTO lv_created_by FROM crmd_orderadm_h WHERE guid = <s_guid>-value.
IF sy-subrc = 0.
    <created_by> = lv_created_by.


DATA: lv_created_by TYPE crmd_opport_h-fld00008b.
SELECT SINGLE fld00008b INTO lv_created_by FROM crmd_opport_h WHERE guid = <s_guid>-value.
IF sy-subrc = 0.
   <created_by> = lv_created_by.

finally replace the hard code value in step1 with model binding, and that’s all.


Now the extension field could support both read and update function.

Complete frontend source code could be found in github:

commit id:


Last Part

In next blog, the steps how to enable the creation on extension field will be introduced.

Assigned Tags

      You must be Logged on to comment or reply to a post.
      Author's profile photo Former Member
      Former Member

      Hi Jerry,

      I have implemented the same. When i see the inspect element the custom field value is not getting passed. Just the GUID and if any standard field change.

      The extHookAddCustomHeaderFields field is getting called but custom field value is not getting passed to the backend.

      Please help.



      Author's profile photo Former Member
      Former Member


      I have the same problem. Did you find any solution ?

      Best regards