cancel
Showing results for 
Search instead for 
Did you mean: 

Adjust value selected by user before applying ALV filter in Web Dynpro ABAP

KKilhavn
Active Contributor
0 Kudos

An application displays a 1:N relationship as a comma-separated list of the selected values. This column can thus contain values such as '' (no value selected), 'B' (only value B selected), 'A,B,C' (values A, B and C selected) etc.

The ALV standard filter functionality will then present a list of all combinations to let the user select a filter. Instead I want to let the user select from the possible individual values (i.e. just '', 'A', 'B' and 'C' instead of '', 'A',A,B', 'A,C' and so on).

When the user selects a value the filter then has to be adjusted from EQ 'B' to CP '*B*' before it is applied.

I have managed to present the list of individual filter values by setting the key/value list in the FILTER_VALUES context node of SALV_WD_TABLE.
I also have an entry with key --NULL-- to represent the empty set.

However, I have *not* been able to adjust the filter before it is applied. I have tried two different event handlers, ON_STD_FUNCTION_BEFO and ON_STD_FUNCTION_AFTE.

Currently the code I have tried to apply is as follows. The methods have been defined on the view that contains the ALV, but it shouldn't really matter where the methods are implemented.

DATA(lo_model) = wd_this->wd_cpifc_alv( )->get_model( ).
DATA(lo_field) = lo_model->if_salv_wd_field_settings~get_field( 'FIELD' ).
LOOP AT lo_field->if_salv_wd_filter~get_filter_rules( ) ASSIGNING FIELD-SYMBOL(<fs_filter_rule>).
  IF <fs_filter_rule>-r_filter_rule->get_operator( ) = 'EQ'.
    IF <fs_filter_rule>-r_filter_rule->get_low_value( ) = '--NULL--'.
      <fs_filter_rule>-r_filter_rule->set_low_value( '' ).
    ELSE.
      <fs_filter_rule>-r_filter_rule->set_low_value( '*' && <fs_filter_rule>-r_filter_rule->get_low_value( ) && '*' ).
      <fs_filter_rule>-r_filter_rule->set_operator( 'CP' ).
    ENDIF.
  ENDIF.
ENDLOOP.

When event ON_STD_FUNCTION_BEFO is processed the filter has not been set yet, so the loop is not entered.

When event ON_STD_FUNCTION_AFTE is processed the filter has been set, and I am able to adjust it. However, the change is not taken into consideration (which makes sense since it is after the standard function has been performed). If I subsequently set a filter on another field the adjusted filter takes effect for this field.

There are at least three possible solutions I suppose, but I have not found a way to implement any of them - so now I hope someone else has implemented this type of functionality and can give me a hint.

The three possible solutions I see are as follows, but I'll gladly discard them and go for another if someone can point me in the right direction.

1) Pick up the value the user selected in ON_STD_FUNCTION_BEFO and set the filter (ideally cancelling the standard function to avoid that it too sets a filter).

2) Make the component pick up the adjustment in ON_STD_FUNCION_AFTE and apply the adjusted filter before refreshing the display.

3) Implement another event handler or add code to another standard method to trigger a display refresh so the adjusted filter is taken account.

Accepted Solutions (1)

Accepted Solutions (1)

KKilhavn
Active Contributor

I won't say it's pretty, but I found a solution that seems to work as desired for my needs. Previously I tried to adjust the values of the existing filter (the operator and the low value). However, it turns out that if I add a filter rule instead of changing the existing rule details, the display will be refreshed automagically for the new filter!

However, care must be taken to not keep adding rules when filters are set for other columns, so the filter is only adjusted when there is a single filter rule. Updated code for those who wish to copy it (and perhaps find a better solution that can be shared back):

DATA(lo_model) = wd_this->wd_cpifc_alv( )->get_model( ).
DATA(lo_field) = lo_model->if_salv_wd_field_settings~get_field( 'FIELD' ).
IF lines( lo_field->if_salv_wd_filter~get_filter_rules( ) ) = 1
  LOOP AT lo_field->if_salv_wd_filter~get_filter_rules( ) ASSIGNING FIELD-SYMBOL(<fs_filter_rule>).
    IF <fs_filter_rule>-r_filter_rule->get_operator( ) = 'EQ'.<br>      DATA(l_low_value) = <fs_filter_rule>-r_filter_rule->get_low_value( ).
      IF l_low_value = '--NULL--'.
         lo_field->if_salv_wd_filter~delete_filter_rule( 1 ).
         lo_field->if_salv_wd_filter~create_filter_rule( included   = 'X'
                                                         operator   = 'EQ'
                                                         low_value  = '' ).
       ELSEIF l_low_value IS NOT INITIAL.
         lo_field->if_salv_wd_filter~create_filter_rule( included   = 'X'
                                                         operator   = 'CP'
                                                         low_value  = l_low_value && ',*' ).
         lo_field->if_salv_wd_filter~create_filter_rule( included   = 'X'
                                                         operator   = 'CP'
                                                         low_value  = '*,' && l_low_value && ',*' ).
         lo_field->if_salv_wd_filter~create_filter_rule( included   = 'X'
                                                         operator   = 'CP'
                                                         low_value  = '*,' && l_low_value ).
       ENDIF.
    ENDIF.
  ENDLOOP.
ENDIF.

This works for simple selection from the dropdown list of predefined filters, and seems to not break anything else 🙂

KKilhavn
Active Contributor
0 Kudos

No-one has suggested a better solution yet, so I am closing this and accepting my own solution as the best answer 🙂

Answers (0)