Monday, 5 October 2020

Showing an avatar with Initials or Image on the Fiori Element Object Page for a better user experience using RAP

I always felt like something is missing in all the FE Object Page apps when there is no avatar displayed in the header. I mean, just check the below image, and see how beautiful it looks with the avatar control on the object page.

SAP ABAP Exam Prep, SAP ABAP Learning, SAP ABAP Tutorial and Material, SAP ABAP Certification, SAP ABAP Guides, SAP ABAP Prep

Versus without image

SAP ABAP Exam Prep, SAP ABAP Learning, SAP ABAP Tutorial and Material, SAP ABAP Certification, SAP ABAP Guides, SAP ABAP Prep

Without an avatar, it’s just ugly, right? (In my opinion)

Question:


- How to display an avatar on the object page? (Normal Image)

SAP ABAP Exam Prep, SAP ABAP Learning, SAP ABAP Tutorial and Material, SAP ABAP Certification, SAP ABAP Guides, SAP ABAP Prep

- What if we don’t have an image? (And still wanted to display some alternative) Then we can show the Initials of the object (Ex. Customer Name Initials)’

SAP ABAP Exam Prep, SAP ABAP Learning, SAP ABAP Tutorial and Material, SAP ABAP Certification, SAP ABAP Guides, SAP ABAP Prep

How to display an avatar on the object page? (Normal Image)


It’s pretty easy and most of you folks know as well. It’s by using the annotation imageURL.

But how to do it in an ABAP RAP based application? One way is by using Virtual Elements.

And In ABAP RAP virtual elements can only be used in the CDS Projection View. So let’s create one Customer Root View .

@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Customer FE Image'
define root view entity Z_I_CUSTOMER_FE_IMAGE
  as select from /DMO/I_Customer as customer
{
  key customer.CustomerID,
      customer.FirstName,
      customer.LastName,
      customer.Title,
      customer.Street,
      customer.PostalCode,
      customer.City,
      customer.CountryCode,
      customer.PhoneNumber,
      customer.EMailAddress,
      customer._Country
}

and it’s a projection view

@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Customer FE Image'

@UI.headerInfo:{
    imageUrl: 'CustImageURL',
    title:{ value: 'CustomerID'},
    typeName: 'Customer Detail',
    typeNamePlural: 'Customers',
    description:{ value: 'FirstName' }
}

define root view entity z_c_customer_fe_image
  as projection on Z_I_CUSTOMER_FE_IMAGE as customer
{

 @UI.facet: [{
      id: 'CustomerHeader',
      purpose:  #STANDARD ,
      type:     #IDENTIFICATION_REFERENCE,
      label:    'General Information' } ]


      @UI.selectionField: [{
          position: 10
       }]
      @UI.lineItem: [{
         position: 10
       }]
      @UI.identification:[{position: 10}]
  key customer.CustomerID,
      @UI.lineItem: [{
         position: 20
       }]
      @UI.identification:[{position: 20}]
      customer.FirstName,
      @UI.lineItem: [{
         position: 30
       }]
      @UI.identification:[{position: 30}]
      customer.LastName,
      
      @ObjectModel.virtualElementCalculatedBy: 'ABAP:ZCL_VE_CUST_INITIAL'
      virtual CustImageURL: abap.string( 256 ),
      
      customer.CountryCode,
      @UI.identification:[{position: 40}]
      @UI.lineItem: [{
         position: 40
       }]
      customer.PhoneNumber,

      @UI.identification:[{position: 50}]
      @UI.lineItem: [{
         position: 50
       }]
      customer.EMailAddress,
      customer._Country
}
 
So I created the virtual element “CustImageURL” and the class ZCL_VE_CUST_INITIAL.  Class is as shown below:

CLASS zcl_ve_cust_initial DEFINITION
  PUBLIC
  FINAL
  CREATE PUBLIC.

  PUBLIC SECTION.
    INTERFACES if_sadl_exit_calc_element_read.
  PROTECTED SECTION.
  PRIVATE SECTION.
ENDCLASS.

CLASS zcl_ve_cust_initial IMPLEMENTATION.
  METHOD if_sadl_exit_calc_element_read~calculate.

    DATA customers TYPE STANDARD TABLE OF z_c_customer_fe_image WITH DEFAULT KEY.
    customers = CORRESPONDING #( it_original_data ).

    LOOP AT customers ASSIGNING FIELD-SYMBOL(<customer>).
      <customer>-CustImageURL = 'https://github.githubassets.com/images/modules/open_graph/github-octocat.png'.
    ENDLOOP.

    ct_calculated_data = CORRESPONDING #(  customers ).
  ENDMETHOD.

  METHOD if_sadl_exit_calc_element_read~get_calculation_info.
  ENDMETHOD.

ENDCLASS.
 
As you can see, I am just passing a dummy images URL, in normal scenarios, we will pass images based on the object ID.

Then create the Service Definition & Service binding.

SAP ABAP Exam Prep, SAP ABAP Learning, SAP ABAP Tutorial and Material, SAP ABAP Certification, SAP ABAP Guides, SAP ABAP Prep

Now consume the same in the Fiori List Report application generated from BAS.

SAP ABAP Exam Prep, SAP ABAP Learning, SAP ABAP Tutorial and Material, SAP ABAP Certification, SAP ABAP Guides, SAP ABAP Prep

Run the App and verify.

SAP ABAP Exam Prep, SAP ABAP Learning, SAP ABAP Tutorial and Material, SAP ABAP Certification, SAP ABAP Guides, SAP ABAP Prep

Showing an Image in the avatar.

SAP ABAP Exam Prep, SAP ABAP Learning, SAP ABAP Tutorial and Material, SAP ABAP Certification, SAP ABAP Guides, SAP ABAP Prep

So we are successfully able to show the image.

But what if we don’t have an image for that particular object.? Instead we can show the initials.

What if we don’t have an image? :- Showing Initials of an Object in avatar


Now let’s add another virtual element as shown below in the projection view:
      
      @ObjectModel.virtualElementCalculatedBy: 'ABAP:ZCL_VE_CUST_INITIAL'
      virtual CustInital: abap.char( 2 ),

Add the below code in the virtual element class

METHOD if_sadl_exit_calc_element_read~get_calculation_info.
    LOOP AT it_requested_calc_elements ASSIGNING FIELD-SYMBOL(<fs_calc_element>).
      CASE <fs_calc_element>.
        WHEN 'CUSTINITAL'.
          APPEND 'FIRSTNAME' TO et_requested_orig_elements.
          APPEND 'LASTNAME' TO et_requested_orig_elements.
      ENDCASE.
    ENDLOOP.
  ENDMETHOD.

Commenting the below image URL code, so the initials will appear.

  METHOD if_sadl_exit_calc_element_read~calculate.
    DATA customers TYPE STANDARD TABLE OF z_c_customer_fe_image WITH DEFAULT KEY.
    customers = CORRESPONDING #( it_original_data ).

    LOOP AT customers ASSIGNING FIELD-SYMBOL(<customer>).
      <customer>-CustInital =  |{ <customer>-FirstName(1) }{ <customer>-LastName(1) }|.
      " <customer>-CustImageURL = 'https://github.githubassets.com/images/modules/open_graph/github-octocat.png'.
    ENDLOOP.

    ct_calculated_data = CORRESPONDING #(  customers ).
  ENDMETHOD.

Now let’s go to the business application studio and Open the service modeler and copy the headerinfo annotation locally.

SAP ABAP Exam Prep, SAP ABAP Learning, SAP ABAP Tutorial and Material, SAP ABAP Certification, SAP ABAP Guides, SAP ABAP Prep

Add the below annotation and add the initials property to the path

SAP ABAP Exam Prep, SAP ABAP Learning, SAP ABAP Tutorial and Material, SAP ABAP Certification, SAP ABAP Guides, SAP ABAP Prep

Now Let’s run the app again and check.

SAP ABAP Exam Prep, SAP ABAP Learning, SAP ABAP Tutorial and Material, SAP ABAP Certification, SAP ABAP Guides, SAP ABAP Prep

So that’s it, using a simiple annotation like this can increase the UX by many folds. This is not available in ABAP yet, maybe will be released in the future by SAP. So for now, we need to add this annotation locally.

No comments:

Post a Comment