Value Help with Additional Binding in RAP – Filtering Storage Locations by Plant in Material Stock Management
Introduction:
In this blog, I will demonstrate how to implement Value Help with Additional Binding in a RAP (RESTful ABAP Programming) application for the MM module. The scenario involves managing Material Stock Information by providing value help for Plant (WERKS) and Storage Location (LGORT). The key feature is filtering the storage location list dynamically based on the selected plant, enhancing the user experience.
When the user selects a Plant, the system automatically filters the Storage Location (LGORT) list to show only the storage locations related to the selected plant.
The requirement is to build a Fiori-based RAP application that enables users to:
Select a Plant from the dropdown. Dynamically filter the Storage Locations based on the selected Plant. Display and manage material stock details such as material number, plant, storage location, stock quantity, and unit of measure.
Procedure:
Key Tables Involved
1. I have created three custom tables, where Storage and plant table have records:
zvs_dt_storage_l → Storage Locations table with data@EndUserText.label : ‘Table for storage location’
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zvs_dt_storage_l {
key client : abap.clnt not null;
key lgort : lgort_d not null;
key lgobe : abap.char(16) not null;
werks : werks_d;
}
Table Data:
zvs_dt_plant_dt → Plant Data@EndUserText.label : ‘Table for plant data’
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zvs_dt_plant_dt {
key client : abap.clnt not null;
key werks : werks_d not null;
name1 : abap.char(30);
}
Table Data:
zvs_dt_mat_stock → Material Stock Data @EndUserText.label : ‘table to store the material stock data.’
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zvs_dt_mat_stock {
key client : abap.clnt not null;
key matnr : matnr not null;
werks : werks_d;
lgort : lgort_d;
@Semantics.quantity.unitOfMeasure : ‘zvs_dt_mat_stock.meins’
labst : abap.quan(13,3);
meins : meins;
}
2.1 Now create one interface view ‘ZVS_I_PLANT_DT’ on top of DB table ‘ZVS_DT_PLANT_DT’: –
This view provides the value help for Plant (WERKS).
I have used the annotation “@ObjectModel.resultSet.sizeCategory: #XS” which makes the value help appear as a dropdown.
@AbapCatalog.sqlViewName: ‘ZVS_PLANT_DT’
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘interface view for plant data’
@Metadata.ignorePropagatedAnnotations: true
@ObjectModel.resultSet.sizeCategory: #XS
define view zvs_i_plant_dt as select from zvs_dt_plant_dt
{
key werks as Werks,
name1 as Name1
}
2.2 Now create interface view ‘ZVS_I_STORAGE_LC’ on top of DB table ‘ZVS_DT_STORAGE_L’: –
This view filters Storage Locations by Plant using additional binding.
This view selects Storage Location, Description, and Plant. The Plant field acts as the filter when the user selects a Plant. @AbapCatalog.sqlViewName: ‘ZVS_STORAGE_LC’
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘interface view for storage location’
@Metadata.ignorePropagatedAnnotations: true
define view zvs_i_storage_lc as select from zvs_dt_storage_l
{
key lgort as StorageLocation,
lgobe as StorageLocDesc,
werks as Plant
}
2.3 Now create interface view ‘ZVS_I_MAT_STOCK’ on top of DB table ‘ZVS_DT_MAT_STOCK’: –
An Interface View (zvs_i_mat_stock) for fetching material stock data with associations to plant and storage location details.
This view maps to the custom table zvs_dt_mat_stock. It includes fields for Material Number, Plant, Storage Location, Stock Quantity, and Unit of Measure @AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘interface view for material stock’
@Metadata.ignorePropagatedAnnotations: true
define root view entity zvs_i_mat_stock as select from zvs_dt_mat_stock
association[0..*] to zvs_i_plant_dt as _plant on $projection.Werks = _plant.Werks
association[0..*] to zvs_i_storage_lc as _storage on $projection.Lgort = _storage.StorageLocation
{
key matnr as Matnr,
werks as Werks,
lgort as Lgort,
@Semantics.quantity.unitOfMeasure: ‘meins’
labst as Labst,
meins as Meins,
_plant,
_storage.StorageLocDesc // Expose description from Storage association
}
3. Now create one consumption view ‘ZVS_C_MAT_STOCK’ on top of Interface view ‘ZVS_I_MAT_STOCK’: –
The consumption view zvs_c_mat_stock projects the data from the interface view zvs_i_mat_stock. This view is intended to expose the data for transactional operations, such as create, update, and delete. The consumption view allows clients to interact with the data, but the actual persistence and behavior are managed through the behavior definition.
@AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘consumption view for material stock’
@Metadata.ignorePropagatedAnnotations: true
@Metadata.allowExtensions: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
define root view entity zvs_c_mat_stock provider contract transactional_query
as projection on zvs_i_mat_stock
{
key Matnr,
Werks,
Lgort,
@Semantics.quantity.unitOfMeasure: ‘meins’
Labst,
Meins,
/* Associations */
_plant,
StorageLocDesc
}
4. Define Metadata Extension
Add Value Help with Additional Binding to your RAP Business Object.
Here:
This “@Consumption.valueHelpDefinition: [{ entity : { element: ‘Werks’ , name: ‘zvs_i_plant_dt’ } }]” Annotation to get the dropdown for WERKS(Plant) Field. This “@Consumption.valueHelpDefinition: [{ entity : { element: ‘StorageLocation’ , name: ‘zvs_i_storage_lc’ }, additionalBinding: [{ element: ‘Plant’ ,localElement: ‘Werks’ }] }]” Annotation here, for additional binding. So based on selected plant it will dynamically filter the storage location.
The @Consumption.valueHelpDefinition annotation is used to define value help (similar to F4 help in SAP GUI) for a field. It allows you to provide dropdown-style suggestions or search help for users when they enter data into specific fields.
entity: Specifies the data source for the value help. element: ‘StorageLocation’: The field in the current CDS view where the value help is applied. name: ‘zvs_i_storage_lc’: The CDS view providing the value help data. additionalBinding: Defines additional filtering criteria. element: ‘Plant’: The field in the value help entity used for filtering. localElement: ‘Werks’: The field in the current view that is used as the filtering key.
Metadata Extension Code for your reference:
@Metadata.layer: #CORE
annotate entity zvs_c_mat_stock with
{
.facet: [{
id: ‘MaterialStock’,
purpose: #STANDARD,
type: #IDENTIFICATION_REFERENCE,
label: ‘Material ID’,
position: 10
}]
: { lineItem: [{ position: 10, label: ‘Material no.’ }],
identification: [{ position: 10, label: ‘Material no.’ }] }
Matnr;
: { lineItem: [{ position: 20, label: ‘Plant’ }],
identification: [{ position: 20, label: ‘Plant’ }] }
@Consumption.valueHelpDefinition: [{ entity : { element: ‘Werks’ , name: ‘zvs_i_plant_dt’ } }]
Werks;
: { lineItem: [{ position: 30, label: ‘Storage location’ }],
identification: [{ position: 30, label: ‘Storage location’ }] }
@Consumption.valueHelpDefinition: [{ entity : { element: ‘StorageLocation’ , name: ‘zvs_i_storage_lc’ }
,additionalBinding: [{ element: ‘Plant’ ,localElement: ‘Werks’ }]
}]
Lgort;
: { lineItem: [{ position: 40, label: ‘Stock quantity’ }],
identification: [{ position: 40, label: ‘Stock quantity’ }] }
Labst;
: { lineItem: [{ position: 60, label: ‘Storage location Description’ }],
identification: [{ position: 60, label: ‘Storage location Description’ }] }
StorageLocDesc;
}
5. Define Behavior Definition
The labst (Stock Quantity) and meins (Unit of Measure) fields are read-only. The behavior definition supports CRUD operations.
Now create a behavior definition on top of interface view ‘ZVS_I_MAT_STOCK’:
managed implementation in class zbp_vs_i_mat_stock unique;
strict ( 2 );
define behavior for zvs_i_mat_stock //alias <alias_name>
persistent table zvs_dt_mat_stock
lock master
authorization master ( instance )
//etag master <field_name>
early numbering
{
create;
update;
delete;
field ( readonly ) Matnr, StorageLocDesc;
mapping for zvs_dt_mat_stock{
Matnr = matnr;
Werks = werks;
Lgort = lgort;
Labst = labst;
Meins = meins;
}
}
Now create a behavior definition on top of consumption view ‘ZVS_C_MAT_STOCK’:
projection;
strict ( 2 );
define behavior for zvs_c_mat_stock //alias <alias_name>
{
use create;
use update;
use delete;
}
Go to front-end:
Here I will create one new record:
You can see here, all the storage location are coming if we didn’t provide plant:
So we’ll select plant 1000 from dropdown:
You can see here storage location got filtered based on the selected plant:
If I select plant 1400, so based on that we are getting 0006 storage location:
After saving record you can see the result:
Conclusion:
This blog showed how to create a RAP-based Fiori app with value help that filters storage locations based on the selected plant. Using CDS views, associations, and annotations, the app becomes user-friendly, efficient, and easy to maintain.
Value Help with Additional Binding in RAP – Filtering Storage Locations by Plant in Material Stock Management Introduction:In this blog, I will demonstrate how to implement Value Help with Additional Binding in a RAP (RESTful ABAP Programming) application for the MM module. The scenario involves managing Material Stock Information by providing value help for Plant (WERKS) and Storage Location (LGORT). The key feature is filtering the storage location list dynamically based on the selected plant, enhancing the user experience. When the user selects a Plant, the system automatically filters the Storage Location (LGORT) list to show only the storage locations related to the selected plant. The requirement is to build a Fiori-based RAP application that enables users to: Select a Plant from the dropdown. Dynamically filter the Storage Locations based on the selected Plant. Display and manage material stock details such as material number, plant, storage location, stock quantity, and unit of measure. Procedure: Key Tables Involved 1. I have created three custom tables, where Storage and plant table have records: zvs_dt_storage_l → Storage Locations table with data@EndUserText.label : ‘Table for storage location’
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zvs_dt_storage_l {
key client : abap.clnt not null;
key lgort : lgort_d not null;
key lgobe : abap.char(16) not null;
werks : werks_d;
}Table Data:zvs_dt_plant_dt → Plant Data@EndUserText.label : ‘Table for plant data’
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zvs_dt_plant_dt {
key client : abap.clnt not null;
key werks : werks_d not null;
name1 : abap.char(30);
}Table Data:zvs_dt_mat_stock → Material Stock Data @EndUserText.label : ‘table to store the material stock data.’
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zvs_dt_mat_stock {
key client : abap.clnt not null;
key matnr : matnr not null;
werks : werks_d;
lgort : lgort_d;
@Semantics.quantity.unitOfMeasure : ‘zvs_dt_mat_stock.meins’
labst : abap.quan(13,3);
meins : meins;
} 2.1 Now create one interface view ‘ZVS_I_PLANT_DT’ on top of DB table ‘ZVS_DT_PLANT_DT’: – This view provides the value help for Plant (WERKS). I have used the annotation “@ObjectModel.resultSet.sizeCategory: #XS” which makes the value help appear as a dropdown. @AbapCatalog.sqlViewName: ‘ZVS_PLANT_DT’
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘interface view for plant data’
@Metadata.ignorePropagatedAnnotations: true
@ObjectModel.resultSet.sizeCategory: #XS
define view zvs_i_plant_dt as select from zvs_dt_plant_dt
{
key werks as Werks,
name1 as Name1
}2.2 Now create interface view ‘ZVS_I_STORAGE_LC’ on top of DB table ‘ZVS_DT_STORAGE_L’: – This view filters Storage Locations by Plant using additional binding. This view selects Storage Location, Description, and Plant. The Plant field acts as the filter when the user selects a Plant. @AbapCatalog.sqlViewName: ‘ZVS_STORAGE_LC’
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘interface view for storage location’
@Metadata.ignorePropagatedAnnotations: true
define view zvs_i_storage_lc as select from zvs_dt_storage_l
{
key lgort as StorageLocation,
lgobe as StorageLocDesc,
werks as Plant
}2.3 Now create interface view ‘ZVS_I_MAT_STOCK’ on top of DB table ‘ZVS_DT_MAT_STOCK’: – An Interface View (zvs_i_mat_stock) for fetching material stock data with associations to plant and storage location details. This view maps to the custom table zvs_dt_mat_stock. It includes fields for Material Number, Plant, Storage Location, Stock Quantity, and Unit of Measure @AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘interface view for material stock’
@Metadata.ignorePropagatedAnnotations: true
define root view entity zvs_i_mat_stock as select from zvs_dt_mat_stock
association[0..*] to zvs_i_plant_dt as _plant on $projection.Werks = _plant.Werks
association[0..*] to zvs_i_storage_lc as _storage on $projection.Lgort = _storage.StorageLocation
{
key matnr as Matnr,
werks as Werks,
lgort as Lgort,
@Semantics.quantity.unitOfMeasure: ‘meins’
labst as Labst,
meins as Meins,
_plant,
_storage.StorageLocDesc // Expose description from Storage association
}3. Now create one consumption view ‘ZVS_C_MAT_STOCK’ on top of Interface view ‘ZVS_I_MAT_STOCK’: – The consumption view zvs_c_mat_stock projects the data from the interface view zvs_i_mat_stock. This view is intended to expose the data for transactional operations, such as create, update, and delete. The consumption view allows clients to interact with the data, but the actual persistence and behavior are managed through the behavior definition. @AbapCatalog.viewEnhancementCategory: [#NONE]
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: ‘consumption view for material stock’
@Metadata.ignorePropagatedAnnotations: true
@Metadata.allowExtensions: true
@ObjectModel.usageType:{
serviceQuality: #X,
sizeCategory: #S,
dataClass: #MIXED
}
define root view entity zvs_c_mat_stock provider contract transactional_query
as projection on zvs_i_mat_stock
{
key Matnr,
Werks,
Lgort,
@Semantics.quantity.unitOfMeasure: ‘meins’
Labst,
Meins,
/* Associations */
_plant,
StorageLocDesc
} 4. Define Metadata Extension Add Value Help with Additional Binding to your RAP Business Object. Here: This “@Consumption.valueHelpDefinition: [{ entity : { element: ‘Werks’ , name: ‘zvs_i_plant_dt’ } }]” Annotation to get the dropdown for WERKS(Plant) Field. This “@Consumption.valueHelpDefinition: [{ entity : { element: ‘StorageLocation’ , name: ‘zvs_i_storage_lc’ }, additionalBinding: [{ element: ‘Plant’ ,localElement: ‘Werks’ }] }]” Annotation here, for additional binding. So based on selected plant it will dynamically filter the storage location. The @Consumption.valueHelpDefinition annotation is used to define value help (similar to F4 help in SAP GUI) for a field. It allows you to provide dropdown-style suggestions or search help for users when they enter data into specific fields. entity: Specifies the data source for the value help. element: ‘StorageLocation’: The field in the current CDS view where the value help is applied. name: ‘zvs_i_storage_lc’: The CDS view providing the value help data. additionalBinding: Defines additional filtering criteria. element: ‘Plant’: The field in the value help entity used for filtering. localElement: ‘Werks’: The field in the current view that is used as the filtering key. Metadata Extension Code for your reference:@Metadata.layer: #CORE
annotate entity zvs_c_mat_stock with
{
.facet: [{
id: ‘MaterialStock’,
purpose: #STANDARD,
type: #IDENTIFICATION_REFERENCE,
label: ‘Material ID’,
position: 10
}]
: { lineItem: [{ position: 10, label: ‘Material no.’ }],
identification: [{ position: 10, label: ‘Material no.’ }] }
Matnr;
: { lineItem: [{ position: 20, label: ‘Plant’ }],
identification: [{ position: 20, label: ‘Plant’ }] }
@Consumption.valueHelpDefinition: [{ entity : { element: ‘Werks’ , name: ‘zvs_i_plant_dt’ } }]
Werks;
: { lineItem: [{ position: 30, label: ‘Storage location’ }],
identification: [{ position: 30, label: ‘Storage location’ }] }
@Consumption.valueHelpDefinition: [{ entity : { element: ‘StorageLocation’ , name: ‘zvs_i_storage_lc’ }
,additionalBinding: [{ element: ‘Plant’ ,localElement: ‘Werks’ }]
}]
Lgort;
: { lineItem: [{ position: 40, label: ‘Stock quantity’ }],
identification: [{ position: 40, label: ‘Stock quantity’ }] }
Labst;
: { lineItem: [{ position: 60, label: ‘Storage location Description’ }],
identification: [{ position: 60, label: ‘Storage location Description’ }] }
StorageLocDesc;
}5. Define Behavior DefinitionThe labst (Stock Quantity) and meins (Unit of Measure) fields are read-only. The behavior definition supports CRUD operations. Now create a behavior definition on top of interface view ‘ZVS_I_MAT_STOCK’: managed implementation in class zbp_vs_i_mat_stock unique;
strict ( 2 );
define behavior for zvs_i_mat_stock //alias <alias_name>
persistent table zvs_dt_mat_stock
lock master
authorization master ( instance )
//etag master <field_name>
early numbering
{
create;
update;
delete;
field ( readonly ) Matnr, StorageLocDesc;
mapping for zvs_dt_mat_stock{
Matnr = matnr;
Werks = werks;
Lgort = lgort;
Labst = labst;
Meins = meins;
}
}Now create a behavior definition on top of consumption view ‘ZVS_C_MAT_STOCK’: projection;
strict ( 2 );
define behavior for zvs_c_mat_stock //alias <alias_name>
{
use create;
use update;
use delete;
}Go to front-end:Here I will create one new record: You can see here, all the storage location are coming if we didn’t provide plant: So we’ll select plant 1000 from dropdown: You can see here storage location got filtered based on the selected plant: If I select plant 1400, so based on that we are getting 0006 storage location: After saving record you can see the result: Conclusion:This blog showed how to create a RAP-based Fiori app with value help that filters storage locations based on the selected plant. Using CDS views, associations, and annotations, the app becomes user-friendly, efficient, and easy to maintain. Read More Application Development and Automation Blog Posts articles
#SAP