Application Development and Automation Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
Krishna_karale
Explorer
733

Hello, 
 
In this blog post we are going to Learn about Static Feature Control.

Dynamic Feature Control will see in Next Part.

What is Feature Control in RAP ? 

Feature control in the ABAP RESTful Application Programming (RAP) model is a mechanism used to manage the behavior of user interface elements and operations based on certain conditions. It allows developers to enable or disable features dynamically, ensuring that the UI adapts to the current state of the business object. 

With feature control, you can provide information to the service on how data has to be displayed for consumption in a SAP Fiori UI, for example if fields are mandatory or read-only. 

You can implement feature control in a Static way or Dynamic way 

  • In a Static case, you define which operations are available for each business object entity or which fields have specific access restrictions like being mandatory or ready-only.  
  • In a Dynamic case, the access restrictions for fields or the enabling or disabling of methods depends on the state of the business object, for example on the value of a specific field. 

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 

Krishna_karale_0-1737804775931.png

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
{
  .facet: [{
     purpose: #STANDARD,
     position: 10,
     type : #IDENTIFICATION_REFERENCE,
     label: 'Travel Details'
   }]

  .identification: [{ position: 10, label: 'Travel Id' }]
  .lineItem: [{ label: 'Travel Id' }]
  TravelId;

  .identification: [{ position: 20, label: 'Agency Id' }]
  .lineItem: [{ label: 'Agency Id' }]
  AgencyId;

  .identification: [{ position: 30, label: 'Customer Id' }]
  .lineItem: [{ label: 'Customer Id' }]
  CustomerId;

  .identification: [{ position: 40, label: 'Begin Date' }]
  .lineItem: [{ label: 'Begin Date' }]
  BeginDate;

  .identification: [{ position: 50, label: 'End Date' }]
  .lineItem: [{ label: 'End Date' }]
  EndDate;

  .identification: [{ position: 60, label: 'Booking Fee' }]
  .lineItem: [{ label: 'Booking Fee' }]
  bookingfee;

  .identification: [{ position: 70, label: 'Total Price' }]
  .lineItem: [{ label: 'Total Price' }]
  TotalPrice;

  .identification: [{ position: 80, label: 'Status Confirm' },
  { type: #FOR_ACTION, dataAction: 'status', label: 'Status Confirm' } ]
  .lineItem: [{ label: 'Status' },
  { type: #FOR_ACTION, dataAction: 'status', label: 'Confirm Status' }]
  status;


  .identification: [{ position: 100, label: 'Currency' }]
  .lineItem: [{ label: 'Currency' }]
  CurrencyCode;

  .identification: [{ position: 90, label: 'Description' }]
  .lineItem: [{ label: 'Description' }]
  Description;


  .identification: [{ position: 110, label: 'Created By' }]
  .lineItem: [{ label: 'Created By' }]
  CreatedBy;

  .identification: [{ position: 120, label: 'Created At' }]
  .lineItem: [{ label: 'Created At' }]
  CreatedAt;

  .identification: [{ position: 130, label: 'Last Changed By' }]
  .lineItem: [{ label: 'Last Changed By' }]
  LastChangedBy;

  .identification: [{ position: 140, label: 'Last Changed At' }]
  .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;
}

 

 

Static Feature Control 

Firstly, we will see how to implement Static Feature Control  

Static Feature Controls can be used to set field's properties like if it's a mandatory or read only field. 

Syntax: Field (<Below keywords>)  <Field names> 

Krishna_karale_0-1737805326562.png

In Our Scenario, we are making some fields as mandatory and some fields as Read-only. 

Krishna_karale_1-1737805326564.png

Here we are making LastChangedAt, LastChangedBY, CreatedAt, CreatedBy fields read-only (We can edit them once we they were created). 

These fields (AgencyId, CustomerId, BeginDate, EndDate, Bookingfee and CurrencyCode) make Mandatory, we have to pass the value at any condition else it will throw an error. 

Static Feature control Mechanism. 

We are having this given data. 

Krishna_karale_2-1737805326565.png

When I Try to Create new Record, we can see the mandatory fields. 

The Fields with the star mark are Mandatory Fields. 

Krishna_karale_3-1737805326567.png

Here I am not providing any Value to Travel Id and Booking Fee 

Krishna_karale_4-1737805326568.png

When we try to save it without providing the values, it will throw an error. 

Krishna_karale_5-1737805326569.png

 

Krishna_karale_6-1737805326570.png

After Providing all the valid Values we can save it. 

Krishna_karale_7-1737805326571.png

After this, when we try to edit the values, we can’t edit the Read-Only Fields 

Krishna_karale_8-1737805326572.png

As we can see, the marked fields are in non-editable mode. 

Conclusion. 

In SAP RAP, feature control is essential for managing the behavior of fields, actions, or UI elements. It can be categorized into static feature control and dynamic feature control, each playing a unique role. 

Static Feature Control. 

Static feature control defines behavior at design time using annotations or configurations. For example, fields can be set as read-only, hidden, or editable by default. This approach ensures consistent and predictable behavior across all scenarios. It is ideal for cases where field behavior remains unchanged, such as system-generated fields like creation timestamps or unique identifiers. 

3 Comments
Subbu_chowdary
Explorer
0 Kudos

Thankyou for the information it is very helpful.

Khan-Muskan
Explorer
0 Kudos

Thankyou for the information it is very helpful.

 

Dadapeer
Explorer
0 Kudos

Thank you @Krishna_karale 

Labels in this area