cancel
Showing results for 
Search instead for 
Did you mean: 

Strange issue on row selection in a wd_table

matteo_montalto
Contributor
0 Kudos

Hi all gurus,

I'm working on an SRM 7 system, specifically on the WD Component /SAPSRM/WDC_CTR_DOTC_IT, view V_CTR_DODC_ITEMS.

In the view there's a table showing items of a contract; we created a custom button ("item deletion") which simply triggers a method that sets the field ZZ_DEL_IND value to 'X' for the selected line(s).

Here's the method code:

METHOD onactionzdelete .

  DATA lv_action              TYPE /sapsrm/pdo_action_type.
  DATA lo_transaction_context TYPE REF TO /sapsrm/cl_transaction_context.

* Get instance of transaction object
  lo_transaction_context ?= /sapsrm/cl_transaction_context=>/sapsrm/if_transaction_context~get_instance( ).
* Set action id
  lv_action = 'DELETE_ITEM'.
  lo_transaction_context->set_current_action( iv_current_action = lv_action ).
* start ZZDEL_IND management
  DATA : lon_ctr_item     TYPE REF TO if_wd_context_node.
  DATA : lt_elem_set      TYPE wdr_context_element_set.
  DATA : ls_element       TYPE REF TO if_wd_context_element.
  DATA : deleted          TYPE abap_bool.

  CALL METHOD wd_context->get_child_node
    EXPORTING
      name       = 'CTR_ITEM'
    RECEIVING
      child_node = lon_ctr_item.

* Get the selected elements of the item table
  lt_elem_set  = lon_ctr_item->get_selected_elements( abap_true ).
* for each selected element, set ZZ_DEL_IND value
* Get the static attributes of all SELECTED elements into an internal table
  LOOP AT lt_elem_set INTO ls_element.
    CALL METHOD ls_element->set_attribute
      EXPORTING
        value = abap_true
        name  = 'ZZ_DEL_IND'.

    CALL METHOD ls_element->set_changed_by_client
      EXPORTING
        flag = abap_true.
  ENDLOOP.

  CALL METHOD wd_comp_controller->mo_bom_ctr->/sapsrm/if_cll_bo_mapper~fire_event_refresh( ).
ENDMETHOD.

Now, the problem:

- if I select a single row and press the button, ZZ_DEL_IND is set correctly for the selected row;

- if I select all the positions using the standard button SELECT->SELECT ALL , ZZ_DEL_IND is set correctly for all the selected rows;

BUT...

- if I select more than a single position (holding CTRL key down), ZZ_DEL_IND is NOT set.

In debug, I've seen that the problems are in the fire_event_refresh( ), which in case of single selection or all positions selected triggers correctly an update process, while in case of multiple selection "by hand" does not.

In details: /sapsrm/if_cll_bo_mapper~fire_event_refresh triggers a method:

me->/sapsrm/if_cll_xo_mapper~fire_event_update( )

which itself launches the update process:

me->fire_event_update( IMPORTING ev_update_performed = ev_update_performed )

Here, the method extracts all the mappers for the WD and loops over them to check for something changed:

LOOP AT lt_mapper ASSIGNING <ls_mapper>.
      CLEAR: lv_exception_occured, lv_update_performed.
      IF <ls_mapper>-mapper->is_ui_changed_by_client( ) EQ abap_true.
....

And that's the problem; when processing the mapper -> (in debug), I can see that:

- when a single row is selected, or all the rows are selected via "SELECT ALL" standard method, then the mapper results changed by client (the above condition is then satisfied)...

- while in case of multiple selection , is_ui_changed_by_client( ) = abap_false.

Has anyone suggestions on how to overcome this problem? I guess it deals with multiple selection process.

Thanks in advance

Accepted Solutions (1)

Accepted Solutions (1)

Former Member
0 Kudos

> * Get the selected elements of the item table

> lt_elem_set = lon_ctr_item->get_selected_elements( abap_true ).

> * for each selected element, set ZZ_DEL_IND value

> * Get the static attributes of all SELECTED elements into an internal table

> LOOP AT lt_elem_set INTO ls_element.

> CALL METHOD ls_element->set_attribute

> EXPORTING

> value = abap_true

> name = 'ZZ_DEL_IND'.

>

> CALL METHOD ls_element->set_changed_by_client

> EXPORTING

> flag = abap_true.

> ENDLOOP.

>

> CALL METHOD wd_comp_controller->mo_bom_ctr->/sapsrm/if_cll_bo_mapper~fire_event_refresh( ).

> ENDMETHOD.

I must say that this is a long post and i have difficulty to understand what exactly your problem is.

Are you trying to say that your code

lt_elem_set = lon_ctr_item->get_selected_elements( abap_true ).

returns 0 elements when you select the rows with CTRL key ?

If this is true then i would advice you to contact SAP support desk.

matteo_montalto
Contributor
0 Kudos

>

> I must say that this is a long post and i have difficulty to understand what exactly your problem is.

>

> Are you trying to say that your code

> lt_elem_set = lon_ctr_item->get_selected_elements( abap_true ).

> returns 0 elements when you select the rows with CTRL key ?

>

> If this is true then i would advice you to contact SAP support desk.

Hello Baskaran and thanks for your help,

no, that statement return exactly the selected items. But:

- in case of a single row selection (lt_elem_set has cardinality EQ 1), everything's fine; same if all the positions have been selected via "Select All" standard button;

- in case of multiple selection with CTRL key, lt_elem_set is correctly filled with the selected rows but then:

CALL METHOD wd_comp_controller->mo_bom_ctr->/sapsrm/if_cll_bo_mapper~fire_event_refresh( ).

does not trigger effectively an update, as expected.

I tried to investigate further the issue and the results are on my previous post. Shortly, it seems that the problem arise in that method call, at this point, as:

IF <ls_mapper>-mapper->is_ui_changed_by_client( ) EQ abap_true.
".... do what I'd expect

the statement returns abap_false, that is to say, the "view" mapper seems not to be changed. This happens only when a multiple selection with CTRL key has been performed before pushing my custom button.

Thanks again for your help and patience.

Former Member
0 Kudos

Hallo Matteo,

This could be a bug, anyway report to the SAP support desk.

Meantime , you can do a work around that after the lt_elem_set is filled, loop trough them and set is_changed_by_client to true.

This is not elegant solution but this would work.

matteo_montalto
Contributor
0 Kudos

Hello Baskaran,

as you can see from the sketch of code, I already did that:

LOOP AT lt_elem_set INTO ls_element.
    CALL METHOD ls_element->set_attribute
      EXPORTING
        value = abap_true
        name  = 'ZZ_DEL_IND'.
 
    CALL METHOD ls_element->set_changed_by_client
      EXPORTING
        flag = abap_true.
  ENDLOOP.

This however does not work anyway.

Thanks again!

gill367
Active Contributor
0 Kudos

may be this can help

Use

/SAPSRM/IF_CLL_XO_MAPPER~FIRE_EVENT_REFRESH( ).

as

/SAPSRM/IF_CLL_bo_MAPPER~FIRE_EVENT_REFRESH( ). is obselete.

thanks

sarbjeet singh

Former Member
0 Kudos

My mistake, Sorry for that. Perhaps you could try what Sarbjeet suggests.

matteo_montalto
Contributor
0 Kudos

Hello,

I tried to replace:

CALL METHOD wd_comp_controller->mo_bom_ctr->/sapsrm/if_cll_bo_mapper~fire_event_refresh( ).

with:

CALL METHOD wd_comp_controller->mo_bom_ctr->/SAPSRM/IF_CLL_XO_MAPPER~FIRE_EVENT_REFRESH( ).

but this does not work, even in case of single item selection or "select all" selection via standard button. I'm wondering if the problem is then in my loop routine to assign 'abap_true' to the ZZ_DEL_IND attribute of all the selected lines...

gill367
Active Contributor
0 Kudos

Regarding the ctrl + slection thing, the problem is no event is trigerred when you do this manual selection.

so as no event is getting triggered, is_UI_changed_by_client is coming as false.

in case of select all or selection using shift key the value will be true.

may be if possible use check boxes as one more column

matteo_montalto
Contributor
0 Kudos

Hi sarbjeet,

I guess you got it, the point to focus is the missing event triggered (therefore, is_UI_changed_by_client for the mapper returns abap_false). Unfortunately, I cannot modify the standard table/layout so I have to work on what standard gives.

Now, since I can easily retrieve the selected items , is there any way to workaround on such behavior? In example, when the lt_elem_set is not empty, can I trigger an event so that the system recognize the fact that the UI has been changed by client?

matteo_montalto
Contributor
0 Kudos

Another idea I had, looking for hint or suggestions about the feasibility:

I can get the selected items; then I could loop over them and trigger the method which is executed by standard when a row is selected:

ONACTIONROW_SELECT

and then do my assignment. Basically, I'm trying to "unroll" a multiple selection of N elements into N steps of single selection process.

in order to do this I need to build ad-hoc an event (TYPE REF TO CL_WD_CUSTOM_EVENT) but don't know how to do it.

I've seen that parameters for the standard wdevent are:

ID -> CTR_ITEM

CONTEXT_ELEMENT -> initial

ROW -> row_index (I can get it from the selected element list)

NEW_ROW_ELEMENT -> the selected element (I can get it from the selected element list)

OLD_ROW_ELEMENT -> can be omitted (leave blank).

Could this trick be feasible? thanks in advance for your support.

gill367
Active Contributor
0 Kudos

hey

i tried doing something in 7.0 ehp1.

there i am finding diff things i am not able to select the rows using ctrl key.

thanks

sarbjeet singh

matteo_montalto
Contributor
0 Kudos

I found something that seems useful here:

[http://help.sap.com/saphelp_nw70ehp2/helpdata/en/4b/5d0d7a7f142b5fe10000000a42189c/content.htm]

in particular, differences between the onSelect and onLeadSelect actions.

By default, the wd I'm working on has the following table events - action bindings::

onLeadSelect -> row_select

onSelect, as a consequence, empty.

I tried the following modification (yes, I know, it's "technically" a standard modification, anyway I'm doing some attempts to make things work):

onLeadSelect -> empty

onSelect -> onSelect (that's a std action defined in the WD... perhaps SAP provided both ways to let the customer choose?)

Anyway... Let's go for a good and a bad news:

- the good one: onSelect is triggered anytime an item position is selected, and triggers an event, so... seems THE solution.

- the bad one: it dumps 😄 and here's the motive... this is the standard code of onSelect:

METHOD onactionon_select .
* Object reference
  DATA: loe_context_element   TYPE REF TO if_wd_context_element.
* Constants
  DATA: lc_context_element  TYPE string VALUE 'CONTEXT_ELEMENT'.
***
* Get context element
----> loe_context_element = wdevent->get_context_element( name = lc_context_element ). <-----
  loe_context_element->set_changed_by_client( ).

* Call mapper class' hadle approve hier item mehtod
  wd_this->mo_dodm_ctr_items->/sapsrm/if_cll_do_tree_mapper~handle_approve_hier_item( io_wd_event = wdevent ).
ENDMETHOD.

The problem is in the marked line, as wdevent has the parameter with name CONTEXT_ELEMENT set to INITIAL.

As a consequence, loe_context_element is initial and the set_changed_by_client() method dumps - OBJECTS_OBJREF_NOT_ASSIGNED_NO.

What am I doing wrong? I simply swapped from onLeadSelect use to onSelect one, using methods provided by the standard. Can anyone help on this point? Seems quite an interesting task

Edited by: Matteo Montalto on Feb 22, 2011 10:39 PM

Former Member
0 Kudos

Hoi Matteo,

According to the help document, [http://help.sap.com/saphelp_nw70ehp1/helpdata/en/2d/390e422dfcde2ce10000000a1550b0/content.htm|http://help.sap.com/saphelp_nw70ehp1/helpdata/en/2d/390e422dfcde2ce10000000a1550b0/content.htm]

onSelect event handler method automatically transfers

ID,CONTEXT_ELEMENT,OLD_LEAD_SELECTION,NEW_LEAD_SELECTION.

You can insert them directly as importing parameters and you can avoid using local variable to read it from wdevent.

You can check in debug if CONTEXT_ELEMENT,OLD_LEAD_SELECTION,NEW_LEAD_SELECTION are filled. If they are not filled then i assume that something to do with selectionchangebeahviour.

gill367
Active Contributor
0 Kudos

I guess this stadard parameter has some problem with onlead selec and onselect events.

it is more useful when selection type is single no lead or multinolead.

so what you can do is comment out these line from the onselect



loe_context_element = wdevent->get_context_element( name = lc_context_element ). <-----
  loe_context_element->set_changed_by_client( ).

because any ways you are doing this set_changed_by_client( ) on the full selection in the

eventhandler of the button.

thanks

sarbjeet singh

matteo_montalto
Contributor
0 Kudos

>

> onSelect event handler method automatically transfers

>

> ID,CONTEXT_ELEMENT,OLD_LEAD_SELECTION,NEW_LEAD_SELECTION.

>

> You can insert them directly as importing parameters and you can avoid using local variable to read it from wdevent.

>

>

> You can check in debug if CONTEXT_ELEMENT,OLD_LEAD_SELECTION,NEW_LEAD_SELECTION are filled. If they are not filled then i assume that something to do with selectionchangebeahviour.

Hi Baskaran and thanks for your always valuable help,

as far as I've seen in debug, the CONTEXT_ELEMENT parameter has always value INITIAL.

Tried also to change the selectionchangebehaviour, which has three possible values: auto (default by standard), manual and ifNoLoss. None of them worked for that issue.

I guess this could be a standard bug, anyway opening a note to SAP isn't that easy because - technically speaking - we have changed a standard view layout property (because the table events by standard are set w.r.t. the onLeadSelect method).

Any hint or suggestion on the argument? it's a pity since using onSelect makes the event trigger even on multiple selections (that is to say, adding positions to the selection by CTRL+clicking on them), so it seems exactly what we're looking for.

matteo_montalto
Contributor
0 Kudos

>

> so what you can do is comment out these line from the onselect

>


> 
> loe_context_element = wdevent->get_context_element( name = lc_context_element ). <-----
>   loe_context_element->set_changed_by_client( ).
> 
> 

>

> because any ways you are doing this set_changed_by_client( ) on the full selection in the

> eventhandler of the button.

Hi sarbjeet, thanks for your support.

I'm gonna try it, but the doubt is... what if the user selects a row and fills an inputfield ? If we suppress that set_changed_by_client( ) on the selection, the system probably does not react correctly (unless the user triggers the onEnter event on the inputField, but how can we be sure about that?).

Shortly... are we sure that suppressing that set_changed_by_client is an invariant w.r.t. user's operativity?

Thanks again.

EDIT: I tried to override the standard onActionOnSelect method to bypass that two lines but still get a dump. Probably, CONTEXT_ELEMENT parameter is also used by the following call:

wd_this->mo_dodm_ctr_items->/sapsrm/if_cll_do_tree_mapper~handle_approve_hier_item( io_wd_event = wdevent ).

so the dump:

OBJECTS_OBJREF_NOT_ASSIGNED_NO

Access via 'NULL' object reference not possible.

Edited by: Matteo Montalto on Feb 23, 2011 11:18 AM

gill367
Active Contributor
0 Kudos

Hi

1. where exactly you are getting the null reference then.

2. and in case of ONleadslect and onselect both we can get the element also by using the node

use the method get_lead_selection on the node which is acting as the data source of the table.

say its name is 'NODE1'

then


data nd type ref to if_wd_context_node.
nd = wd_context->get_child_node(  'NODE1'  ).
data el type ref to if_Wd_context_element.

el = nd->get_lead_selection(   ).

thanks

sarbjeet singh

matteo_montalto
Contributor
0 Kudos

Hi sarbjeet,

1) I did as follow: on se80->layout tab for the view, I selected the table and associate, under the section Events, onSelect to the method ON_SELECT (which is standard).

Then, when I select a row in the table, the dump occours since in wd_event, the parameter CONTEXT_ELEMENT is initial.

So (following code is from the standard onActionOnSelect method):

loe_context_element = wdevent->get_context_element( name = lc_context_element ).

returns an empty (initial element), therefore the dump.

2) supposing I can retrieve the context element in the way you described; I could simply override the onActionOnSelect method in order to get the context element before triggering the following statements:

* Call mapper class' hadle approve hier item mehtod
  wd_this->mo_dodm_ctr_items->/sapsrm/if_cll_do_tree_mapper~handle_approve_hier_item( io_wd_event = wdevent ).

But before that, I should modify wdevent's parameter in order to populate correctly the CONTEXT_ELEMENT parameter. Right? Is it possible to do that at runtime?

Thanks again.

gill367
Active Contributor
0 Kudos

Ok

so use the get_lead_select to get the lead selection and pass it a paramter to a newly created custom event.

pass this event to the method ->/sapsrm/if_cll_do_tree_mapper~handle_approve_hier_item

Try this. i was just wondering what was the real problem and where we are heading.

anyways, here is the code for the same.


  data el type ref to if_Wd_context_element.

  data nd type ref to if_Wd_context_node.
  nd = wd_context->get_child_node( 'NODE1' ).   
  el = nd->get_lead_selection( ).
data wpr type table of WDR_EVENT_PARAMETER.
data wpr1 type  WDR_EVENT_PARAMETER_LIST.

DATA dref TYPE REF TO DATA.


create data dref type ref to if_Wd_context_element.
get reference of el into dref.

data wps type WDR_EVENT_PARAMETER.
wpr = wdevent->parameters.
data newevt type ref to cl_Wd_custom_event.
loop at wpr into wps.
  if wps-name = 'CONTEXT_ELEMENT'.
    wps-value = dref.
    modify wpr from wps.
    endif.
*    insert wps into wpr1.

  endloop.

wpr1 = wpr.

create object newevt             "pass this event to that method.
exporting
  name = 'SELECT'
  parameters = wpr1.
wd_this->mo_dodm_ctr_items->/sapsrm/if_cll_do_tree_mapper~handle_approve_hier_item( io_wd_event = newevt ).

matteo_montalto
Contributor
0 Kudos

>

> Try this. i was just wondering what was the real problem and where we are heading.

>

Shortly: I have created a button which should set a custom field, ZZ_DEL_IND, to 'X' for all the selected rows.

This works if the selection is a single selection or in case of a "select all" selection, but doesn't work if the selection is a multiple one done pressing CTRL + click on the rows.

That's why I'm trying to switch from onLeadSelect to onSelect, as it manages with an event also the CTRL + click selection.

Hope it's a bit clearer now; i'm gonna try your purposed solution and provide a feedback. In the meantime, thanks for your help.

EDIT: I tried the purposed solution and:

- I had a PDO layer error that closed the browser when selecting the the third row...

- get_lead_selection() returns always the first selected row (highlighted) and not the new one selected by CTRL+click.

I'm a bit stuck'd on the problem, I guess I'll revert to standard behaviour (using onLeadSelect instead of onSelect) and renounce to allow multiple selections via CTRL key for the task. This would be however a big limitation for the customers.

Edited by: Matteo Montalto on Feb 23, 2011 1:52 PM

Answers (1)

Answers (1)

matteo_montalto
Contributor
0 Kudos

Hello gurus,

I solved on my own with a workaround. Quite tricky; I'm looping over the selected position, set the current position as a lead selection by triggering the event handle_lead_position with custom parameters (built in my method) and then processing the single position. Kinda complicated, but it works

Former Member
0 Kudos

Salve Matteo,

potresti farci una cortesia: se è possibile inviarci un esempio di codice che hai utilizzato per risolvere detto problema? Abbiamo cercato di risolverlo ma non ci siamo riusciti. Please.

Ti ringrazio.

Un conterraneo....