
Hello,
In this blog post we are going to Learn about Dynamic Feature Control in RAP.
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.
This function is an optional feature provided by the RAP Framework, which complements existing functionalities. While it is not a mandatory component, it can be utilized to enhance certain aspects of the application. In the current example, this function has not yet been implemented, but we will explore its usage in this article. Specifically, feature control can be applied to fields to modify or influence their behavior, such as controlling their visibility or editability.
When implementing this feature, you need to decide how to apply it:
Procedure
Here we are defining a Custom table (ZKK_DT_TRAVEL).
The table zkk_dt_travel is a transparent table in SAP that stores travel-related information. It includes details such as travel ID, agency ID, customer ID, travel dates, booking fees, total price, currency, status and a description. It also tracks the creation and modification details like created by, created at, last changed by, and last changed at.
@EndUserText.label : 'Travel table'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zkk_dt_travel {
key client : abap.clnt not null;
key travel_id : /dmo/travel_id not null;
agency_id : /dmo/agency_id;
customer_id : /dmo/customer_id;
begin_date : /dmo/begin_date;
end_date : /dmo/end_date;
@Semantics.amount.currencyCode : '/dmo/travel_m.currency_code'
booking_fee : abap.curr(16,2);
@Semantics.amount.currencyCode : '/dmo/travel_m.currency_code'
total_price : /dmo/total_price;
currency_code : /dmo/currency_code;
description : /dmo/description;
status : abap_boolean;
created_by : abp_creation_user;
created_at : abp_creation_tstmpl;
last_changed_by : abp_locinst_lastchange_user;
last_changed_at : abp_locinst_lastchange_tstmpl;
}
The Above table holds the records which are given below
For this database table(ZKK_DT_TRAVEL) we are defining the Basic view/Interface view.
The ZKK_I_TRAVEL is a CDS view based on the zkk_dt_travel table. It provides a structured way to access travel data, including fields like travel ID, agency ID, customer ID, travel dates, booking fees, total price, currency, and timestamps. It uses annotations to enhance usability, such as semantic tags for amounts, currencies, and metadata for created/changed users and timestamps.
@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'Interface view for Travelling'
@Metadata.ignorePropagatedAnnotations: true
@Metadata.allowExtensions: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
define root view entity ZKK_I_TRAVEL
as select from zkk_dt_travel
{
key travel_id as TravelId,
agency_id as AgencyId,
customer_id as CustomerId,
begin_date as BeginDate,
end_date as EndDate,
@Semantics.amount.currencyCode: 'CurrencyCode'
booking_fee as bookingfee,
@Semantics.amount.currencyCode: 'CurrencyCode'
total_price as TotalPrice,
currency_code as CurrencyCode,
description as Description,
status as status,
@Semantics.user.createdBy: true
created_by as CreatedBy,
@Semantics.systemDateTime.createdAt: true
created_at as CreatedAt,
@Semantics.user.localInstanceLastChangedBy: true
last_changed_by as LastChangedBy,
@Semantics.systemDateTime.lastChangedAt: true
last_changed_at as LastChangedAt
}
Now I am defining the Projection view on top of interface view.
@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'projection view for Travel'
@Metadata.ignorePropagatedAnnotations: true
@Metadata.allowExtensions: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
define root view entity ZKK_C_TRAVEL
as projection on ZKK_I_TRAVEL as Travel
{
key TravelId,
AgencyId,
CustomerId,
BeginDate,
EndDate,
@Semantics.amount.currencyCode: 'CurrencyCode'
bookingfee,
@Semantics.amount.currencyCode: 'CurrencyCode'
TotalPrice,
CurrencyCode,
Description,
status,
CreatedBy,
CreatedAt,
LastChangedBy,
LastChangedAt
}
Now I am defining the Metadata Extension for projection View.
@Metadata.layer: #PARTNER
annotate entity ZKK_C_TRAVEL with
{
@UI.facet: [{
purpose: #STANDARD,
position: 10,
type : #IDENTIFICATION_REFERENCE,
label: 'Travel Details'
}]
@UI.identification: [{ position: 10, label: 'Travel Id' }]
@UI.lineItem: [{ label: 'Travel Id' }]
TravelId;
@UI.identification: [{ position: 20, label: 'Agency Id' }]
@UI.lineItem: [{ label: 'Agency Id' }]
AgencyId;
@UI.identification: [{ position: 30, label: 'Customer Id' }]
@UI.lineItem: [{ label: 'Customer Id' }]
CustomerId;
@UI.identification: [{ position: 40, label: 'Begin Date' }]
@UI.lineItem: [{ label: 'Begin Date' }]
BeginDate;
@UI.identification: [{ position: 50, label: 'End Date' }]
@UI.lineItem: [{ label: 'End Date' }]
EndDate;
@UI.identification: [{ position: 60, label: 'Booking Fee' }]
@UI.lineItem: [{ label: 'Booking Fee' }]
bookingfee;
@UI.identification: [{ position: 70, label: 'Total Price' }]
@UI.lineItem: [{ label: 'Total Price' }]
TotalPrice;
@UI.identification: [{ position: 80, label: 'Status Confirm' },
{ type: #FOR_ACTION, dataAction: 'status', label: 'Status Confirm' } ]
@UI.lineItem: [{ label: 'Status' },
{ type: #FOR_ACTION, dataAction: 'status', label: 'Status' }]
status;
@UI.identification: [{ position: 100, label: 'Currency' }]
@UI.lineItem: [{ label: 'Currency' }]
CurrencyCode;
@UI.identification: [{ position: 90, label: 'Description' }]
@UI.lineItem: [{ label: 'Description' }]
Description;
@UI.identification: [{ position: 110, label: 'Created By' }]
@UI.lineItem: [{ label: 'Created By' }]
CreatedBy;
@UI.identification: [{ position: 120, label: 'Created At' }]
@UI.lineItem: [{ label: 'Created At' }]
CreatedAt;
@UI.identification: [{ position: 130, label: 'Last Changed By' }]
@UI.lineItem: [{ label: 'Last Changed By' }]
LastChangedBy;
@UI.identification: [{ position: 140, label: 'Last Changed At' }]
@UI.lineItem: [{ label: 'Last Chnaged at' }]
LastChangedAt;
}
Now I am defining the Behavior Definition for Interface/Basic view.
managed implementation in class zbp_kk_i_travel unique;
strict ( 2 );
define behavior for ZKK_I_TRAVEL alias Travel //alias <alias_name>
persistent table zkk_dt_travel
lock master
authorization master ( instance )
//etag master <field_name>
{
create;
update;
delete;
field ( readonly : update ) TravelId;
field ( readonly ) LastChangedAt, LastChangedBy, CreatedAt, CreatedBy;
field ( mandatory : create ) AgencyId, CustomerId, BeginDate, EndDate, bookingfee, CurrencyCode;
action ( features : instance ) status result [1] $self;
mapping for ZKK_DT_TRAVEL {
TravelId = travel_id;
AgencyId = agency_id;
CustomerId = customer_id;
BeginDate = begin_date;
EndDate = end_date;
bookingfee = booking_fee;
TotalPrice = total_price;
CurrencyCode = currency_code;
Description = description;
status = status;
CreatedBy = created_by;
CreatedAt = created_at;
LastChangedBy = last_changed_by;
LastChangedAt = last_changed_at;
}
}
Create the Behavior Definition for Projection view.
projection;
//strict ( 2 );
define behavior for ZKK_C_TRAVEL alias Travel //alias <alias_name>
{
use create;
use update;
use delete;
use action status;
}
Here in behavior definition of interface view we have to use Feature control with Actions.
After this we have to implement 2 methods, Status and get_instance_feature method.
Here is the class.
CLASS lhc_ZKK_I_TRAVEL DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS get_instance_authorizations FOR INSTANCE AUTHORIZATION
IMPORTING keys REQUEST requested_authorizations FOR travel RESULT result.
METHODS status FOR MODIFY
IMPORTING keys FOR ACTION travel~status RESULT result.
METHODS get_instance_features FOR INSTANCE FEATURES
IMPORTING keys REQUEST requested_features FOR travel RESULT result.
ENDCLASS.
CLASS lhc_ZKK_I_TRAVEL IMPLEMENTATION.
METHOD get_instance_authorizations.
ENDMETHOD.
METHOD status.
MODIFY ENTITIES OF zkk_i_travel IN LOCAL MODE
ENTITY Travel UPDATE FIELDS ( status )
WITH VALUE #( for key in keys ( %tky = key-%tky status = abap_true ) )
FAILED failed
REPORTED reported.
read ENTITIES OF zkk_i_travel IN LOCAL MODE
ENTITY Travel ALL FIELDS WITH CORRESPONDING #( keys )
RESULT data(travel_data).
result = VALUE #( for travel_record in travel_data
( %tky = travel_record-%tky %param = travel_record )
).
ENDMETHOD.
METHOD get_instance_features.
read ENTITIES OF zkk_i_travel IN LOCAL MODE
ENTITY Travel
FIELDS ( status ) WITH CORRESPONDING #( keys )
RESULT data(confirmed_status)
FAILED failed.
result = VALUE #( for trav in confirmed_status
let con_status = cond #( when trav-status = abap_true
THEN if_abap_behv=>fc-o-disabled
else if_abap_behv=>fc-o-enabled )
IN ( %tky = trav-%tky
%action-status = con_status
)
).
ENDMETHOD.
ENDCLASS.
Implement the method Status with functionality triggered by the button. This method can include any business logic based on the requirements. In the current scenario, it sets the field value to True.
The method GET_INSTANCE_FEATURES has been implemented to manage the control states (Enable or Disable in the current scenario). If the Status Confirmed is Yes then The Status button will be Disabled.
Run Application.
Scenario: If the Status Confirmed is ‘NO’ then we can change it to ‘Yes’, Using Confirm Status Button on list page. If Status Confirmed is ‘Yes’ then the button will be Disable.
As we can see the status in above image is No, if we select the particular field the Confirm Status will be enabled.
If we Confirm the status then the value will become ‘YES’
When we select the fields with Status ‘YES’ the button will be in disables State.
Conclusion
Dynamic Feature Control
Dynamic feature control allows for runtime adjustments based on specific business logic or conditions. This is implemented using RAP methods like GET_INSTANCE_FEATURES. It enables controls to adapt based on context, such as user roles, permissions, or the status of the business object. For instance, the "Approve" button might be enabled only for records in the "Pending Approval" state, or a "Cancel" button could become inactive after the travel date has passed.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
9 | |
5 | |
4 | |
4 | |
2 | |
2 | |
2 | |
2 | |
2 |