RAP - Feature Control
This article is about the Feature Control, a mechanism to dynamically enable or disable features in the RAP based on the state of the object.
Table of contents
With Feature Control, the various fields and properties can be adjusted again at runtime, for example to activate or deactivate actions. In this article you will learn more about how to use this function to get more flexibility in your data model.
Introduction
This function is provided by the RAP Framework, but is not a "must-have", but can be used as an option to the existing functions. In the current state of our example, we have not yet used this function and will try it with this article. Feature control can be used on fields to affect certain properties, on standard operations (e.g.: update, delete) and on actions to enable or disable them.
In the end you have to decide how to implement the feature:
- Instance-based feature ("features:instance") - The data of the individual instance is available to you, it is decided per instance how the feature is handled.
- Global feature ("features:global") - There is no access to the data, but a decision is made once whether the feature can be used or not.
Instance feature
Now let's look at the instance-based features and how we can properly use them. To do this, we extend the "fillEmptyStreets" action. This action is currently always active when a record is selected. However, we would now like to change this action so that the button can only be pressed if no street is filled in the data record. To do this, you must now include the corresponding feature in the definition:
action ( features : instance ) fillEmptyStreets result [1] $self;
After expanding the action, you can now activate the behavior definition and you will see a definition-level warning. Now the operation has to be implemented, you can simply go to the name of the entity and use CTRL + 1 to implement the necessary method:
Now that the method "get_instance_feature" has been implemented, let's take a look at the signature of the method to see what data we can calculate with:
Once again, we have more parameters at our disposal than were actually defined in the signature. Let's take a closer look at the most important parameters:
- KEYS - Transfer all instances to be checked. When the list loads for the first time, all records to be displayed are loaded.
- REQUESTED FEATURES - Structure where the features to be checked are marked. Is used for the different tests.
- RESULT - Result of the entities for which the feature should be deactivated
Now that the basics have been defined and the import parameters of the method are clear, we can now start with the implementation. In the first step, we check which feature is to be checked. Then we read the appropriate data and transfer the individual data records to the results table:
IF requested_features-%action-fillEmptyStreets = if_abap_behv=>mk-on.
READ ENTITIES OF ZBS_I_RAPPartner IN LOCAL MODE
ENTITY Partner FIELDS ( Street ) WITH CORRESPONDING #( keys )
RESULT DATA(lt_partner_data).
LOOP AT lt_partner_data INTO DATA(ls_partner).
DATA(ld_deactivate) = COND #(
WHEN ls_partner-Street IS INITIAL THEN if_abap_behv=>mk-off
ELSE if_abap_behv=>mk-on
).
INSERT VALUE #(
partnernumber = ls_partner-PartnerNumber
%action-fillemptystreets = ld_deactivate
) INTO TABLE result.
ENDLOOP.
ENDIF.
Hint: The features are all activated by default and must now be deactivated for the entities that do not match. So after optimizing the code above, the example can also look like this:
IF requested_features-%action-fillEmptyStreets = if_abap_behv=>mk-on.
READ ENTITIES OF ZBS_I_RAPPartner IN LOCAL MODE
ENTITY Partner FIELDS ( Street ) WITH CORRESPONDING #( keys )
RESULT DATA(lt_partner_data).
LOOP AT lt_partner_data INTO DATA(ls_partner) WHERE Street IS NOT INITIAL.
INSERT VALUE #(
partnernumber = ls_partner-PartnerNumber
%action-fillemptystreets = if_abap_behv=>mk-on
) INTO TABLE result.
ENDLOOP.
ENDIF.
Now let's take a look at the result in the app, if we mark a data record that already has a stored street, then the button is now deactivated:
If we now mark a data record for which no street is maintained, the button is activated and we can use the action in RAP:
Global Feature
In the next example we want to restrict a feature on a global level, namely the deletion of records via the app. The feature is currently enabled for everyone who can use the app. To do this, we extend the operation in the behavior definition as we did earlier for the instance feature.
delete ( features : global );
To implement a global feature, the "get_global_features" method must be implemented. As previously described, there is no transfer of the keys from the outside. The derivation of the various features must be based on other criteria. The following example shows an example implementation to make the delete function only available to certain users:
IF requested_features-%delete = if_abap_behv=>mk-on.
DATA(ld_deactivate) = COND #(
WHEN cl_abap_context_info=>get_user_alias( ) = '<USER>' THEN if_abap_behv=>mk-off
ELSE if_abap_behv=>mk-on
).
result-%delete = ld_deactivate.
ENDIF.
Again, you should note that you have to deactivate the feature where it is not needed. The return this time is a structure because we're editing the entire feature (delete) here.
Conclusion
Activating and deactivating individual features in the RAP Business Object should now be no problem for you. You know how to turn off a feature per record and at the entire level, and that the features are always turned on to begin with.