CAP with Fiori Elements: Actions on List Report / Object Page using Annotations – Part2


This blog post serves as a follow-up to the following preceding post:

CAP with Fiori Elements: Actions on List Report / Object Page using Annotations – Part1

Within this blog post, I have outlined my observations regarding the various types of actions achievable through service definition and annotations.

Explanatio of POC Scenario and Its Resources

We will use the sample project “cap-fe-lr-op-actions” that I have shared on GitHub here to explain the concepts. Let’s briefly examine the project and some of its essential files.

Project Structure Folder or File Purpose
db/ Data model is defined in schema.cds

Services are defined in service.cds

Capabilities of services are defined in annotations.cds

app/ This contains UI app.
app/annotations contains all annotation files.
annotations.cds annotations to list report views
generic-actions.cds annotations for generic actions (explained in section 1 of Detailed Explanation)
global-determining-actions.cds annotations for global and determining actions
fieldgroup-actions.cds annotations for actions in field group
table-actions.cds annotations for actions in table
chart-actions.cds annotations for actions in chart
action-varieties.cds annotations for types of actions

Service cap_fe_lr_op_actions_serviceproivides following data set: Roots, Items, Categories, Criticalities, Samples.

Please be aware that in this blog post, my emphasis is on illustrating the functionality of presenting tables in various configurations. It’s worth noting that the service utilized for demonstration purposes may not be flawless and is solely used to explain the functionalities.

Detailed Explanation

Now, let’s explore various types of actions that can be incorporated through annotations. To illustrate, we’ll use the Samples view from the list report within the application (marked above).

  • Critical Action
  • Action with Dialog having Text Input
    • Actions with a dialog are actions that require additional user input, for example, a comment. The system will display a dialog containing one or more input fields for the user to enter the necessary details.
    • To implement an action with a dialog, you can enhance your action by adding extra input parameters as shown below:
      type inText : {
        comment: String;
      entity Samples as projection on db.Samples actions {
        action sba_action_text(text:inText:comment);
    • It is also possible tassign a label text to the input by including a label in the type:
      annotate service.inText:comment with @Common.Label :'MultiLine Input Text';
    • While Text/String inputs typically display as a single-line input field, you can convert them to multiline by applying the following annotation:
      annotate service.inText:comment with @UI.MultiLineText:true;​
    • Result:
  • Action with Multiple Input
    • Actions can have different kinds of input depending upon the type of input parameters defined for the action in the service definition.
    • Let’s look at an example:
      /*=======>> Action Definition <<=======*/
      type inComplexObject : {
        comment : String(50);
        date    : Date;
        datetime: DateTime;
        confirm : Boolean;
        value   : Integer;    
      action sba_action_complex(
          aprcomment  :inComplexObject:comment,
          aprdate     :inComplexObject:date,
          aprdatetime :inComplexObject:datetime,
          aprconfirm  :inComplexObject:confirm
      /*==========>> Annotations <<==========*/
      annotate service.inComplexObject {
        comment   @Common.Label: 'Comment';
        date      @Common.Label: 'Date of Approval';
        datetime  @Common.Label: 'Time of Processing';
        confirm   @Common.Label: 'Confirmation';

      Above action definition and annotations will provide following result:

    • Note: Which type of control will be rendered depends on the data type of the import parameter for the action in the service definition.
  • Action with Mandatory and Default Input
    • It is also possible to make some import parameters of action mandatory and provide default values as well.
    • Here is an example:
      /*=======>> Action Definition <<=======*/  
      type inOtherObject: {
          input1  :String(50);
          input2  :String(50);
          input3  :String(50);
    : '_it'
      action sba_action_other(
          text1 :inOtherObject:input1, 
          @UI.ParameterDefaultValue:'default text'
          text2 :inOtherObject:input2,
          text3 :inOtherObject:input3 
      /*==========>> Annotations <<==========*/
      annotate service.inOtherObject {
        input1  @Common.Label: 'First Input' @mandatory;
        input2  @Common.Label: 'Second Input';
        input3  @Common.Label: 'Third Input';
    • Result:
      If mandatory parameter is not filled by user, then it throw error as shwon
    • Note-1: @mandatory annotation term is used to make the parameter mandatory
      Note-2: @UI.ParameterDefaultValue annotation term is used to provide default value for a parameter. It is also possible to use value of a property of selected context as default value.
    • In above sample, we have value of name property as default value for Third Input parameter.
  • Action with DefaultValueFunction based Input
    • Apart from specifying default values with the @UI.ParameterDefaultValue annotation, it is feasible to retrieve default values from the backend service using a function within the service.
    • Let’s look at an example
      /*=======>> Action Definition <<=======*/
      service cap_fe_lr_op_actions_service {
        type inObjectFn:{
          text1: String;
          text2: String;
        @Common.DefaultValuesFunction: 'cap_fe_lr_op_actions_service.getDefaults'
        action sba_action_defaultfn(text1:inObjectFn:text1, 
                                  @UI.ParameterDefaultValue: 'default value'
                                  text2: inObjectFn:text2);
        function getDefaults() returns inObjectFn;
      /*=======>> Defulat Function <<=======*/
      srv.on(["getDefaults"], async (req) => {
        return {  text1: 'default text 01', 
                  text2: 'default text 02'  };
      /*==========>> Annotations <<==========*/
      annotate service.inObjectFn {
        text1 @Common.Label: 'First Text Input';
        text2 @Common.Label: 'Second Text Input';


    • Result:

    • Note: @UI.ParameterDefaultValue annotation term takes importance over value from DefaultValuesFunction as eveident from above example for text2.
  • Action with Value Help Input
    • In addition to the default value help that appear for date and datetime import parameters, you have the option to include your own custom value helps.
    • Let’s look at example
      /*=======>> Action Definition <<=======*/  
      type inObject :{
        category    : String;
        criticality : String;
      action sba_action_valuehelp(
      /*==========>> Annotations <<==========*/
      annotate service.inObject {
      category @(
        Common.Label: 'Sample Category',
        Common.ValueList : {
          $Type : 'Common.ValueListType',
          CollectionPath : 'Categories',
          Parameters : [
            { $Type : 'Common.ValueListParameterInOut',
              LocalDataProperty : category,
              ValueListProperty : 'id'                       },
            { $Type : 'Common.ValueListParameterDisplayOnly',
              ValueListProperty : 'descr'                    }
          Label : 'Choose One Category'
        Common.ValueListWithFixedValues : false
      criticality @(
        Common.Label: 'Sample Criticality',
        Common.ValueList : {
          $Type : 'Common.ValueListType',
          CollectionPath : 'Criticalities',
          Parameters : [
            { $Type : 'Common.ValueListParameterInOut',
              LocalDataProperty : criticality,
              ValueListProperty : 'id'                       },
            { $Type : 'Common.ValueListParameterDisplayOnly',
              ValueListProperty : 'descr'                    }
          Label : 'Choose One Criticality'
        Common.ValueListWithFixedValues : true
    • Result:
    • Note: Value helps are added to the type of import parameter using @Common.ValueList annotation term.

Miscellanous features

  • Handling Messages 
    • There are 2 ways to show messages on SAP Fiori Elements based UI application: Message Toasters, Message Dialog as shown below:
    • The display of a message toast or a dialog depends on the method utilized in a CAP-based service to communicate the message.
    • It’s worth noting that using the req.notify method produces a message toast, while other methods such as, req.warn, and req.error result in message dialogs with varying severities.
      req.notify('message to be shown on message toast');
      req.error('erroneous message shown on message dialog')​
    • Additionally, when employing, req.warn, req.error, or req.notify, only a single message can be transmitted. To send multiple messages, it is necessary to dispatch all messages from the service using the sap-messages header, as illustrated below:
      srv.on("msg_trigger",async (req) => {
        req._.odataRes.setHeader('sap-messages', JSON.stringify([
            "code" : "500",
            "message" : "info: messages trigger action called!",
            "numericSeverity" : 2                            
            "code" : "504",
            "message" : "This can only be triggered for draft data",
            "numericSeverity" : 3
            "code" : "504",
            "message" : "Error happened! Contact your IT Admin",
            "numericSeverity" : 4

      This results in following message dialog:

  • Criticality for Actions
    • Assigning a criticality level to an action, achieved by configuring the “Criticality” property within the annotation, results with both positive and negative semantic representations.
    • Only two criticality values are supported: #Positive (03), #Negative (01)
    • Please be aware that criticality is not universally supported for all actions; its applicability is limited to inline table actions and global/determining actions on the object page.


In this blog post, we have delved into different kinds of actions generated based on service definition and annotations along with handling messages on SAP Fiori Elements.

Together, the Cloud Application Programming Model and Fiori Elements improve developer experience while also boosting productivity and accelerating the development of enterprise-ready applications.

More information about Fiori Elements with cloud application programming model can be found here. You can follow my profile to get notification of the next blog post on CAP or Fiori Elements. Please feel free to provide any feedback you have in the comments section below and ask your questions about the topic in sap community using this link.

Source link

Be the first to comment

Leave a Reply

Your email address will not be published.