ABAP Blog Posts
cancel
Showing results for 
Search instead for 
Did you mean: 
_Kayky_Mattos_
Explorer
1,042

Hello everyone, recently I came across a somewhat unusual requirement where I needed to use a parameter in a RAP application. As we know, this isn’t natively supported with Fiori Elements, so I had to look for a way to make it work. After some research and a few tests, I ended up with a solution that I consider quite innovative: using a Fiori Freestyle approach.

The best part is that it requires only a minimal amount of code, something that any ABAP developer can implement without much effort, and it becomes extremely useful whenever you need to work with parameters that are not directly linked to the data exposed by the CDS view.

The idea behind this solution is simple:

Since projection views in RAP do not support CDS parameters directly, we expose a parameterized interface CDS view through a service definition and service binding.

Then, using a Fiori Freestyle application with a Smart Table, we dynamically inject the parameter into the table binding path before the data request is sent to the backend.

This allows the RAP service to consume the parameterized CDS view without requiring complex workarounds.

 

Let’s go through the required steps:

 

1)  Since it’s not possible to add WITH PARAMETERS to a projection view, we need to create an interface CDS view and use it as our “projection.”

matttosz_2-1771590856902.png

@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: '<your cds description>'
@Metadata.ignorePropagatedAnnotations: false
@Metadata.allowExtensions: true

define view entity <your_parameterized_interface_cds>
  with parameters
    p_date : abap.char(8)

as select from <your_source_cds_or_table>
(
  p_date : $parameters.p_date
)
{
    key <your_key_field>,
        <your_field_1>,
        <your_field_2>,
        <your_field_3>
}

2) Create our service definition normally

matttosz_4-1771591575874.png

3) Create Service Binding ( Odata V2 )

matttosz_5-1771591628061.png

4) Now we have to create the freestyle app with the fiori generator application

matttosz_6-1771591700764.png

5) Now just connect to the S4 and select the service binding created earlier

matttosz_7-1771591755516.png

At this point, you can see the project structure in the Explorer panel on the left. We’ll focus only on the view and controller folders.

 

 

matttosz_2-1771594013215.png

 

6)

First, we need to create our Smart Table in the view folder. Inside the SmartFilterBar, we must set the entitySet from our service binding. After that, we add a customControl in my case, I used a DatePicker, but you can use any control that fits your requirement. I also attached an onDateChange event to the DatePicker so we can capture and manipulate the selected date whenever it changes.

Within the Smart Table, we also need to define the same entitySet. Another very important point here is the beforeRebindTable event. This is the hook that allows us to pass the parameter to the CDS view. It will trigger the onBeforeRebindTable method in the controller, where we can dynamically inject the parameter into the binding before the data is requested.

matttosz_3-1771594045964.png

 

matttosz_10-1771592364211.png

<mvc:View
    xmlns:table="sap.ui.table"
    xmlns="sap.ui.comp.smartfilterbar"
    xmlns:f="sap.f"
    xmlns:m="sap.m"
    xmlns:mvc="sap.ui.core.mvc"
    xmlns:smartTable="sap.ui.comp.smarttable"
    controllerName="<your.app.namespace>.controller.Main"
    height="100%">

<f:DynamicPage
    id="dynamicPage"
    fitContent="true"
    title="{i18n>appTitle}">

<f:header>
<f:DynamicPageHeader>

<SmartFilterBar
    id="smartFilterBar"
    entitySet="<your_entity_set>">

    <controlConfiguration>

        <ControlConfiguration
            key="<your_parameter_field>"
            visibleInAdvancedArea="true"
            label="<your_filter_label>"
            mandatory="true">

            <customControl>

                <m:DatePicker
                    id="datePicker"
                    displayFormat="dd/MM/yyyy"
                    valueFormat="yyyyMMdd"
                    placeholder="dd/mm/yyyy"
                    width="100%"
                    required="true"
                    change="onDateChange"/>

            </customControl>

        </ControlConfiguration>

    </controlConfiguration>

</SmartFilterBar>

</f:DynamicPageHeader>
</f:header>

<f:content>

<smartTable:SmartTable
    id="smartTable"
    beforeRebindTable="onBeforeRebindTable"
    showRowCount="true"
    enableAutoBinding="false"
    entitySet="<your_entity_set>"
    smartFilterId="smartFilterBar"
    useVariantManagement="true"
    tableType="Table"
    initiallyVisibleFields="<your_fields>"
    enableAutoColumnWidth="true"
    showTablePersonalisation="true">

    <smartTable:customToolbar>

        <m:OverflowToolbar design="Transparent">
            <m:ToolbarSpacer/>
        </m:OverflowToolbar>

    </smartTable:customToolbar>

</smartTable:SmartTable>

</f:content>

</f:DynamicPage>

</mvc:View>

7) In this step, we implement the logic inside the onBeforeRebindTable method, which is responsible for dynamically passing the parameter to the CDS view before the Smart Table triggers the data request.

First, the code retrieves the value entered in the DatePicker using byId. This value will be used as the parameter for the CDS. A local variable (sDate) is initialized to store the selected date.

Next, a validation is performed to ensure that the date field is filled in. Since this parameter is mandatory for the query, if no value is provided the DatePicker is set to the Error state and a validation message is displayed. At the same time, the table binding is stopped using:

oBindingParams.preventTableBind = true;

This prevents the Smart Table from calling the backend without the required parameter, avoiding unnecessary requests and possible errors.

If the date is correctly filled in, any previous error state is cleared by setting the ValueState back to None.

Finally, the most important part happens: the table binding path is updated dynamically. Here we pass the selected date to the parameterized CDS by changing the binding path of the Smart Table:

setTableBindingPath("/<EntitySet>(p_date='${sDate}')/Set")

This is what allows the RAP application to consume a CDS with parameters, because the parameter is injected at runtime just before the data is requested from the backend.

matttosz_12-1771593060014.png

onBeforeRebindTable: function (oEvent) {

    let oDatePicker = this.byId("datePicker");
    let sDate = "";

    if (oDatePicker) {
        sDate = oDatePicker.getValue();
    }

    if (!sDate) {

        if (oDatePicker) {
            oDatePicker.setValueState("Error");
            oDatePicker.setValueStateText("Please inform the date.");
        }

        let oBindingParams = oEvent.getParameter("bindingParams");

        if (oBindingParams) {
            oBindingParams.preventTableBind = true;
        }

        return;
    }

    if (oDatePicker) {
        oDatePicker.setValueState("None");
    }

    this.getView()
        .byId("smartTable")
        .setTableBindingPath("/<your_entity_set>(p_date='" + sDate + "')/Set");

}

And Vooooalá!

matttosz_13-1771593754921.png

Conclusion

Although RAP and Fiori Elements provide powerful tools for building enterprise applications, there are still scenarios where certain features are not directly supported, such as consuming parameterized CDS views in projection layers.

By combining RAP services with a lightweight Fiori Freestyle approach, we can overcome this limitation in a simple and flexible way. Using events like beforeRebindTable and dynamically modifying the binding path allows parameters to be passed to the CDS view at runtime.

This approach requires only a small amount of additional UI code and can be implemented quickly by ABAP developers who are already familiar with RAP and Fiori.

I hope this solution helps others facing similar challenges when working with parameterized CDS views in RAP applications.