If you read my recent blog, HCM Processes & Forms: Making “User Events” Useful Again!, you might have caught on to the very cool fact that in FPM forms, making use of FPM interface classes, we can tell exactly what “event” is triggered and which form field triggered it. Of course, this got my head spinning with all kinds of use cases, but the first that came to mind was the good old, tried-and-true “make selections in a drop-down list control the options in another drop-down list” (also known as “dependent drop-down lists”). But that’s “low hanging fruit”. I thought “how can I make it even cooler?”.

     What if I showed you a way to make a secondary “dependent” drop-down list whose options we populate in response to the “change” event on our primary drop-down (ie. “master”)? But now because I can tell which form field triggers the event, what if I can also populate (add additional entries?) depending on which form field triggered the event (for example a “regular” drop-down list vs. a “super user” drop-down list). So then, we have TWO “master” controls that will fire an event and our “dependent” control will populate accordingly (ie. because it knows WHICH master threw the event).

     First, I built a basic process and form scenario.

Make a simple process

/wp-content/uploads/2014/11/01_586412.jpg

Form Scenario based on FPM form

/wp-content/uploads/2014/11/02_586403.jpg

I defined 3 Form Fields and assigned all the data element “SUBTY” ( a char 4 field). Notice that their “input help” (ie. F4) values are configured to come from my backend service “Y_GS_SOLO”.

/wp-content/uploads/2014/11/03_586404.jpg

User Event

This is a key step. I defined a simple user event, made a field group with our 3 form fields and assigned the field group to the user event.

/wp-content/uploads/2014/11/04_586405.jpg

/wp-content/uploads/2014/11/05_586406.jpg

/wp-content/uploads/2014/11/06_586407.jpg

FPM Form definition/development

I developed my very basic FPM “form” type configuration.

/wp-content/uploads/2014/11/07_586408.jpg

The FPM attributes for the “Food Category” and “Food Category (Super Shopper)” drop down list set the user event “UE_CAT_CHANGE” (from our HCM P&F configuration above) on the “change” event of the drop down list. This is another key step in making it all work.

Backend Generic Service

You might have noticed in the Form Scenario configuration above, I developed one, simple custom backend service “Y_GS_SOLO”. It has one operation “CHECK_CATEGORY” with my 3 fields mapped to it. However, the main “magic” happen in my methods to populate the help values (F4 values).

Before showing off the code, let’s see how this all looks in run time, so you really get the idea of what is going on….

Run Time Testing

First off, you will notice that I have hidden the “admin/super user” field for now. I just want to show how this “dependent” population works from one “master”drop-down. The user first sees….

/wp-content/uploads/2014/11/fpm_1a_586413.jpg

Now we make selection from the “master” drop-down list…

/wp-content/uploads/2014/11/fpm_1b_586414.jpg

We can see in the ABAP debugger that the “event” is caught…

/wp-content/uploads/2014/11/fpm_1c_586416.jpg

And now we can see the new options in the “dependent” drop-down list…

/wp-content/uploads/2014/11/fpm_1d_586418.jpg

If we change the “master” again, we can see how it changes the “dependent” options again..

/wp-content/uploads/2014/11/fpm_1e_586419.jpg

But now, I want to really get you excited about this. Again, because we know WHICH field triggered the event we are “listening” for, we can now react differently.

Here, I add the “admin/super user” field to the form. It will also trigger the same event that the previous, existing “master” drop-down did.

/wp-content/uploads/2014/11/fpm_2a_586420.jpg

Again, we pick from our regular “master” field and get the options populated in the “dependent” drop-down…

/wp-content/uploads/2014/11/fpm_2b_586421.jpg

But now, I pick from the “admin field”…..it fires the same event BUT we know where the even came from. In the debugger, we can see the fieldname of the form field that triggered out event…

/wp-content/uploads/2014/11/fpm_2c_586423.jpg

So, now, we can make a different selection list based on which field fired the event…here, you can see I added option that ONLY the “admin” can pick from…

/wp-content/uploads/2014/11/fpm_2d_586424.jpg

…and again, we make another round of changes and compare….

/wp-content/uploads/2014/11/fpm_2e_586425.jpg

/wp-content/uploads/2014/11/fpm_2f_586426.jpg

So you can imagine that you might have other logic that looks at the form scenario step or the initiator and determines which “master” drop-down to display. But then nothing more is needed for the “dependent” drop-down. It will merely have more or less options available that we handle already in our custom service. Therefore, the same form field can be used regardless. Very cool!

So how is this done? TO THE CODE!!!!! (haha)

First off, in our standard generic service interface method GET_HELP_VALUES, I have a loop that checks which “help” field we are talking about and calls a private method to populate these.

[code]

method IF_HRASR00GEN_SERVICE~GET_HELP_VALUES.
FIELD-SYMBOLS <help_dataset_wa>   TYPE hrasr00gs_help_dataset.

LOOP AT help_datasets ASSIGNING <help_dataset_wa>.
CASE <help_dataset_wa>fieldname.

WHEN C_FLD_FOOD_CATEGORY OR C_FLD_FOOD_CATEGORY_SUPER.   “Category
CALL METHOD me->GET_F4_CATEGORIES
EXPORTING
SPECIAL_FIELDS 
= special_fields
SERVICE_FIELD_VALUES
= service_field_values
CHANGING
HELP_DATASETS
= <help_dataset_wa>.

WHEN C_FLD_FOOD_ITEM.   “Items
CALL METHOD me->GET_F4_ITEMS
EXPORTING
SPECIAL_FIELDS 
= special_fields
SERVICE_FIELD_VALUES
= service_field_values
CHANGING
HELP_DATASETS
= <help_dataset_wa>.
ENDCASE.

ENDLOOP.
endmethod.

[/code]


Here is the code to load up the help values for the “food category”….

[code]

method GET_F4_CATEGORIES.
TYPES : BEGIN OF ty_cat,
code_val
TYPE subty,
code_text
TYPE TEXT40,
END   OF ty_cat.

TYPES : tty_cats TYPE TABLE OF ty_cat.

DATA: service_field_value TYPE hrasr00gensrv_dataset.
DATA: field_catalog       TYPE hrpad_f4help_table_column_tab.
DATA: field_catalog_wa    TYPE hrpad_f4help_table_column.
DATA: lt_cats TYPE tty_cats,
ls_cat
TYPE ty_cat.

FIELD-SYMBOLS <help_values>  TYPE table.

” create field catalog
CLEAR field_catalog.
CLEAR field_catalog_wa.
field_catalog_wa
fieldname = ‘CATEGORY’.
field_catalog_wa
headertitle = ‘Category’.
APPEND field_catalog_wa TO field_catalog.

field_catalog_wafieldname = ‘CATEGORY_TEXT’.
field_catalog_wa
headertitle = ‘Category Text’.
APPEND field_catalog_wa TO field_catalog.

help_datasetsfield_catalog = field_catalog.
help_datasets
keycolumnname = ‘CODE_VAL’.
help_datasets
valuecolumnname = ‘CODE_TEXT’.

CREATE DATA help_datasetsdata TYPE STANDARD TABLE OF ty_cat.
ASSIGN help_datasetsdata->* TO <help_values>.

ls_catcode_val = ‘0’.
ls_cat
code_text = ‘Fruits’.
APPEND ls_cat TO lt_cats.

ls_catcode_val = ‘1’.
ls_cat
code_text = ‘Vegetables’.
APPEND ls_cat TO lt_cats.

ls_catcode_val = ‘2’.
ls_cat
code_text = ‘Meat’.
APPEND ls_cat TO lt_cats.

<help_values> = lt_cats.
endmethod.

[/code]


And here is the code to detect the user event and which field fired it to then build our help values accordingly.

[code]

method GET_F4_ITEMS.
TYPES : BEGIN OF ty_item,
code_val
TYPE subty,
code_text
TYPE TEXT40,
END   OF ty_item.

TYPES : tty_items TYPE TABLE OF ty_item.

DATA: service_field_value TYPE hrasr00gensrv_dataset.
DATA: field_catalog       TYPE hrpad_f4help_table_column_tab.
DATA: field_catalog_wa    TYPE hrpad_f4help_table_column.
DATA: lt_items TYPE tty_items,
ls_item
TYPE ty_item,
lv_cat
TYPE subty.

FIELD-SYMBOLS <help_values>  TYPE table.

* determine event and field it came from
DATA: lt_event_queue    TYPE cl_fpm=>if_fpm~ty_t_event_queue,
ls_first_event   
TYPE cl_fpm=>if_fpm~ty_s_event_queue_entry,
lo_fpm           
TYPE REF TO if_fpm,
lo_event         
TYPE REF TO cl_fpm_event,
lt_params        
TYPE apb_lpd_t_params,
ls_param         
LIKE LINE OF lt_params.
DATA: l_flg_was_admin TYPE bool.

CONSTANTS: c_usr_event_catchange TYPE string VALUE ‘UE_CAT_CHANGE’.

lo_fpm = cl_fpm_factory=>get_instance( ).
CHECK lo_fpm IS BOUND.

lo_fpm->read_event_queue( IMPORTING  et_event_queue = lt_event_queue ).
IF NOT lt_event_queue[] IS INITIAL.
READ TABLE lt_event_queue INTO ls_first_event INDEX 1.
IF ls_first_eventid = c_usr_event_catchange.
“do stuff for our user event!
ENDIF.
“determine which field fired event
lt_params[]
= ls_first_eventparameter.
LOOP AT lt_params INTO ls_param WHERE key EQ ‘FIELDNAME’.
IF ls_paramvalue = C_FLD_FOOD_CATEGORY_SUPER.
l_flg_was_admin
= ‘X’.
READ TABLE service_field_values INTO service_field_value WITH KEY fieldname = C_FLD_FOOD_CATEGORY_SUPER.
IF sysubrc = 0.
lv_cat
= service_field_valuefieldvalue.
ENDIF.
ELSE.
CLEAR l_flg_was_admin.
READ TABLE service_field_values INTO service_field_value WITH KEY fieldname = C_FLD_FOOD_CATEGORY.
IF sysubrc = 0.
lv_cat
= service_field_valuefieldvalue.
ENDIF.
ENDIf.
*      l_event_fieldname = ls_param-value.
EXIT.
ENDLOOP.
ENDIF.

” create field catalog
CLEAR field_catalog.
CLEAR field_catalog_wa.
field_catalog_wa
fieldname = ‘ITEM’.
field_catalog_wa
headertitle = ‘Item’.
APPEND field_catalog_wa TO field_catalog.

field_catalog_wafieldname = ‘ITEM_TEXT’.
field_catalog_wa
headertitle = ‘Item Text’.
APPEND field_catalog_wa TO field_catalog.

help_datasetsfield_catalog = field_catalog.
help_datasets
keycolumnname = ‘CODE_VAL’.
help_datasets
valuecolumnname = ‘CODE_TEXT’.

CREATE DATA help_datasetsdata TYPE STANDARD TABLE OF ty_item.
ASSIGN help_datasetsdata->* TO <help_values>.

CASE lv_cat. “build help based on category selected
WHEN ‘0’. “fruit
ls_item
code_val = ‘0010’.
ls_item
code_text = ‘Apple’.
APPEND ls_item TO lt_items.

ls_itemcode_val = ‘0011’.
ls_item
code_text = ‘Banana’.
APPEND ls_item TO lt_items.

ls_itemcode_val = ‘0012’.
ls_item
code_text = ‘Orange’.
APPEND ls_item TO lt_items.
IF l_flg_was_admin = ‘X’.
ls_item
code_val = ‘0014’.
ls_item
code_text = ‘Pineapple (admin only)’.
APPEND ls_item TO lt_items.

ls_itemcode_val = ‘0016’.
ls_item
code_text = ‘Tomato (admin only)’.
APPEND ls_item TO lt_items.
ENDIF.
WHEN ‘1’. “vegetables
ls_item
code_val = ‘1010’.
ls_item
code_text = ‘Celery’.
APPEND ls_item TO lt_items.

ls_itemcode_val = ‘1011’.
ls_item
code_text = ‘Lettuce’.
APPEND ls_item TO lt_items.

ls_itemcode_val = ‘1012’.
ls_item
code_text = ‘Spinach’.
APPEND ls_item TO lt_items.
IF l_flg_was_admin = ‘X’.

ls_itemcode_val = ‘0016’.
ls_item
code_text = ‘Tomato (admin only)’.
APPEND ls_item TO lt_items.
ENDIF.
WHEN ‘2’. “meat
ls_item
code_val = ‘2010’.
ls_item
code_text = ‘Beef’.
APPEND ls_item TO lt_items.

ls_itemcode_val = ‘2011’.
ls_item
code_text = ‘Fish’.
APPEND ls_item TO lt_items.

ls_itemcode_val = ‘2012’.
ls_item
code_text = ‘Pork’.
APPEND ls_item TO lt_items.
WHEN OTHERS.
ls_item
code_val = ‘0000’.
ls_item
code_text = ‘Please select category.’.
APPEND ls_item TO lt_items.
ENDCASE.

<help_values> = lt_items.
endmethod.

[/code]

The “magic” is really this small piece of code which captures the event and the field that fired it. You can really use this anywhere (ie. in help value methods, your “do operations”, deep within your own private methods, etc.) , so it is quite nice for “event” detection.

[code]

* determine event and field it came from
DATA: lt_event_queue    TYPE cl_fpm=>if_fpm~ty_t_event_queue,
ls_first_event   
TYPE cl_fpm=>if_fpm~ty_s_event_queue_entry,
lo_fpm           
TYPE REF TO if_fpm,
lo_event         
TYPE REF TO cl_fpm_event,
lt_params        
TYPE apb_lpd_t_params,
ls_param         
LIKE LINE OF lt_params.
DATA: l_flg_was_admin TYPE bool.

CONSTANTS: c_usr_event_catchange TYPE string VALUE ‘UE_CAT_CHANGE’. “your event name

lo_fpm = cl_fpm_factory=>get_instance( ).
CHECK lo_fpm IS BOUND.

lo_fpm->read_event_queue( IMPORTING  et_event_queue = lt_event_queue ).
IF NOT lt_event_queue[] IS INITIAL.
READ TABLE lt_event_queue INTO ls_first_event INDEX 1.
IF ls_first_eventid = c_usr_event_catchange. “here we can check for a particular event name
“do stuff for our user event!

“determine which field fired event
lt_params[]
= ls_first_eventparameter.
LOOP AT lt_params INTO ls_param WHERE key EQ ‘FIELDNAME’.
*         l_event_fieldname = ls_param-value. <====this is the field that fired the event
EXIT.
ENDLOOP.

    ENDIF.
ENDIF
.

[/code]

Well, that is it. I hope you really see what is possible now with this, and it gets you as excited as I was when I “discovered” it. It’s not even about drop-down list….it’s about being able to respond (be it adding help values, show/hide fields, populate data, etc) by knowing not only WHAT event was triggered but also WHICH form field triggered it. It makes a lot of things easier and also adds a new level of form interaction. I know I will be using it! As always, I hope this helps others, and I will keep cranking these out as long as you keep reading. Till next time….

To report this post you need to login first.

Be the first to leave a comment

You must be Logged on to comment or reply to a post.

Leave a Reply