SAP Fiori elements Feature Showcase

repository·main·Indexed 43 days ago

https://github.com/sap-samples/fiori-elements-feature-showcase

A demonstration repository and CAP project showcasing implementation patterns for SAP Fiori elements for OData V4, specifically focusing on List Report and Object Page floorplans. It covers features such as draft configuration, custom actions via manifest.json and Controller Extensions, value help with @Common.ValueList, semantic date filters, and various UI annotations for filtering, sorting, and layout.

Tokens
32.4K
Snippets
91
Records
94
Agent score
6%

What's inside SAP Fiori elements Feature Showcase

  1. Overview of Feature Showcase content

    main

    This project serves as a demonstration repository for features available in the List Report and Object Page floorplans using SAP Fiori elements for OData V4.

    Key areas covered include:

    List Report Features

    • General Features: Draft configuration, replacing standard UI texts, custom actions, and default sorting/filtering.
    • Header Area: Variant management, Live Mode, and advanced filter definitions (e.g., mandatory fields, semantic dates, value helps, and dependent filtering).
    • Content Area: Table configurations (types, actions, side effects, CRUD restrictions), multiple views (single/multiple table modes), and various UI enhancements (rating indicators, progress indicators, micro charts, and quick views).

    Object Page Features

    • General Features: Data field annotations (communication, time/date, multi-line text) and custom actions.
    • Header Area: Title/Subtitle configuration, custom actions, and diverse header facets (Address, Data Points, and various Micro Charts).
    • Content Area: Form configurations (connected fields, custom content), table enhancements (variant management, personalization, inline creation), and custom sections/subsections.
    • Footer Bar: Action determination and custom actions.
  2. Define Default Filter Values with @Common.FilterDefaultValue

    main

    Use the @Common.FilterDefaultValue annotation to define initial values for filters.

    Limitations:

    • It does not support complex values.
    • When switching variants, the annotation is no longer considered.

    For complex default values, use the @UI.SelectionPresentationVariant annotation instead.

  3. Define a Selection Presentation Variant (#SPVariant)

    main

    A UI.SelectionPresentationVariant combines a selection (filtering) with a presentation (sorting and visualization). It is similar to a SelectionVariant but includes PresentationVariant properties.

    • SelectionVariant: Defines the filtering logic.
    • PresentationVariant: Defines SortOrder and Visualizations (e.g., which @UI.LineItem to use).
    • You can refer to specialized @UI.LineItem collections by using a qualifier in the Visualizations array.
    annotate srv.RootEntities with @(
        UI.SelectionPresentationVariant #SelectionPresentationVariant : {
            Text : '{i18n>SelectionPresentationVariant}',
            SelectionVariant : {
                $Type : 'UI.SelectionVariantType',
                SelectOptions : [
                    {
                        PropertyName : criticality_code,
                        Ranges : [
                            {
                                Sign : #I,
                                Option : #GT,
                                Low : 0,
                            },
                        ],
                    },
                ],
            },
            PresentationVariant :{
                SortOrder : [
                    {
                        Property : fieldWithPrice,
                        Descending : false,
                    },
                ],
                Visualizations : [
                    '@UI.LineItem#simplified',
                ],
            },
        },
    );
  4. Define the Default Sort Order

    main

    Use the UI.PresentationVariant annotation to establish a default sort order for an entity.

    • SortOrder: An array of objects defining the property and whether it is Descending.
    • Visualizations: An array specifying which line items (e.g., '@UI.LineItem') this sort order should apply to.

    If no sort order is defined, values default to ascending.

    annotate srv.RootEntities with @(
        UI.PresentationVariant :{
            SortOrder : [
                {
                    Property : field,
                    Descending : false,
                },
            ],
            Visualizations : [
                '@UI.LineItem',
            ],
        },
    );
  5. Implement Dependent Filtering in Value Help

    main

    You can create dependent filters where the options in a value help are restricted by another selected value (e.g., selecting a Country filters the available Regions).

    Implementation Patterns:

    • Using ValueListParameterIn: Maps a local property (like country_code on the header) to a property in the value help collection. This acts as an input parameter to filter the target collection.
    • Using ValueListParameterConstant: Statically filters the value help by a fixed value (e.g., always filtering by country_code = 'DE').
    • Multi-Input/Parent Entity Reference: For multi-input fields, you can reference properties from the parent entity in the LocalDataProperty of a ValueListParameterIn parameter.
    annotate schema.RootEntities with{
        ...
        region @(Common : {
            Text            : region.name,
            TextArrangement : #TextFirst,
            ValueListWithFixedValues: true,
            ValueList       : {
                Label          : '{i18n>Region}',
                CollectionPath : 'Regions',
                Parameters     : [
                    {
                        $Type             : 'Common.ValueListParameterInOut',
                        ValueListProperty : 'code',
                        LocalDataProperty : region_code
                    },
                    {
                        $Type             : 'Common.ValueListParameterOut',
                        ValueListProperty : 'name',
                        LocalDataProperty : region.name,
                    },
                    {
                        $Type : 'Common.ValueListParameterFilterOnly',
                        ValueListProperty : 'country_code',
                    },
                    {
                        $Type : 'Common.ValueListParameterIn',
                        LocalDataProperty : country_code,
                        ValueListProperty : 'country_code',
                    },
                ]
            }
        });
    });
  6. Implement toggleable Side Content on Object Pages

    main

    Object Page sections and subsections can have toggleable side content defined via XML fragments in manifest.json.

    Configuration:

    • template: The namespace and name of the XML fragment.
    • equalSplit: If true, the screen splits 1:1. If false or undefined, the split is 2:1 (favoring the original content).

    Triggering Side Content: Use the this.base.getExtensionAPI().showSideContent("[side-content-key]") function within a controller extension or custom action to toggle the visibility. You can also pass a second boolean parameter to set visibility directly instead of toggling.

    "customSectionQualifier": {
        "sideContent": {
            "template": "sap.fe.showcase.lrop.ext.SideContent",
            "equalSplit": true
        }
    }
    // In a Controller Extension
    toggleSideContent(oBindingContext: ODataContextBinding) {
        this.base.getExtensionAPI().showSideContent("customSectionQualifier");
    }
  7. Trigger a Creation Dialog using @Core.Immutable

    main

    To force a creation dialog to pop up for specific fields when creating a new entity, annotate those fields with @Core.Immutable. Because these fields cannot be updated after creation, the system requires the values to be provided during the initial creation step.

    annotate srv.RootEntities {
        ...
        stringProperty @Core.Immutable;
        ...
    };
  8. Define a Selection Variant (#SVariant)

    main

    A UI.SelectionVariant defines how fields in an entity set should be filtered and sorted.

    • Text: The title of the view.
    • SelectOptions: Contains the filtering parameters (sorting/filtering logic).
    • The Option property in Ranges supports: EQ (Equal To), BT (Between), LE (Less than or equal to), GE (Greater than or equal to), NE (Not equal to), GT (Greater than), and LT (Less than).
    annotate srv.RootEntities with @(
        UI.SelectionVariant #variant1 : {
            Text : '{i18n>SVariant1}',
            SelectOptions : [
                {
                    PropertyName : criticality_code,
                    Ranges : [
                        {
                            Sign : #I,
                            High : 2,
                            Option : #BT,
                            Low : 0,
                        },
                    ],
                },
            ],
        },
        ...
    );
  9. Add Subpages to Object Page

    main

    To add a subpage, you must configure two parts in manifest.json:

    1. Routing: Add a new route with a pattern matching the child entity navigation and a name.
    2. Targets: Define a target of type Component using the sap.fe.templates.ObjectPage template, specifying the entitySet in its settings.
    3. Navigation: In the parent entity's controlConfiguration, map the child entity attribute to the new route name.
    // 1. Route
    "routes": [
        {
            "pattern": "RootEntities({key})/ChildEntities1({key2}):?query:",
            "name": "childEntities1ObjectPage",
            "target": "childEntities1ObjectPage"
        }
    ],
    // 2. Target
    "targets": {
        "childEntities1ObjectPage": {
            "type": "Component",
            "id": "childEntities1ObjectPage",
            "name": "sap.fe.templates.ObjectPage",
            "options": {
                "settings": {
                    "entitySet": "ChildEntities1"
                }
            }
        }
    }
    // 3. Navigation Mapping
    "navigation": {
        "childEntities1": {
            "detail": {
                "route": "childEntities1ObjectPage"
            }
        }
    }
  10. Implement a Tree Table for Hierarchical Data

    main

    To display parent-child hierarchies using a TreeTable, you must perform three steps:

    1. Manifest Configuration: Set the table type to TreeTable and provide a hierarchyQualifier in manifest.json.
    2. CDS Annotation: Define the hierarchy using @Aggregation.RecursiveHierarchy. The hierarchyQualifier in the manifest must match the qualifier used here. The ParentNavigationProperty must point back to the same entity.
    3. CAP Requirements: Add specific hierarchy properties (like LimitedDescendantCount, DistanceFromRoot, etc.) to your entity and ensure they are queryable in the database. These properties should be marked as non-filterable and non-sortable via Capabilities annotations.
    // 1. Define the hierarchy in CDS
    annotate srv.OrganizationalUnits @Aggregation.RecursiveHierarchy #OrgUnitsHierarchy : {
      ParentNavigationProperty : superOrdinateOrgUnit,
      NodeProperty             : ID,
    };
    
    // 2. Add required properties for Fiori elements
    extend srv.OrganizationalUnits with @(
      Hierarchy.RecursiveHierarchy #OrgUnitsHierarchy : {
        LimitedDescendantCount : LimitedDescendantCount,
        DistanceFromRoot       : DistanceFromRoot,
        DrillState             : DrillState,
        LimitedRank            : LimitedRank
      },
      Capabilities.FilterRestrictions.NonFilterableProperties: [
        'LimitedDescendantCount', 'DistanceFromRoot', 'DrillState', 'LimitedRank'
      ],
      Capabilities.SortRestrictions.NonSortableProperties    : [
        'LimitedDescendantCount', 'DistanceFromRoot', 'DrillState', 'LimitedRank'
      ],
    ) columns {
      null as LimitedDescendantCount : Int16,
      null as DistanceFromRoot       : Int16,
      null as DrillState             : String,
      null as LimitedRank            : Int16,
    };
  11. Replace standard UI texts using enhanceI18n

    main

    You can override standard SAP Fiori elements UI texts by providing a custom i18n file.

    1. Create a new i18n file (e.g., customI18N.properties).
    2. Reference this file in your manifest.json under the specific entity's settings using the enhanceI18n key.

    Key patterns for overrides:

    • C_COMMON_DIALOG_OK: Applies to all entities.
    • C_TRANSACTION_HELPER_OBJECT_PAGE_CONFIRM_DELETE_WITH_OBJECTTITLE_SINGULAR|EntityName: Applies to a specific entity.
    • C_OPERATIONS_ACTION_CONFIRM_MESSAGE|EntityName|actionName: Applies to a specific action on a specific entity.

    Example key format in .properties file: C_COMMON_ACTION_PARAMETER_DIALOG_CANCEL|RootEntities = Custom cancel text

    "RootEntityListReport": {
        ...
        "options": {
            "settings": {
                ...
                "enhanceI18n": "i18n/customI18N.properties",
                ...
            }
        }
    },
  12. Implement Multiple Table Mode for multiple views

    main

    Multiple table mode uses an icon tab bar above the table to switch between views. Each tab represents a distinct view with its own table, toolbar, and variant management.

    Key Characteristics:

    • Each view must have a unique key in manifest.json.
    • You can use @UI.SelectionPresentationVariant to control presentation.
    • You can display a different entity set in a tab by providing an entitySet property in the manifest.json path entry. When using a different entity set, counts are shown automatically, ignoring the showCounts setting. Filters from the main entity set are applied to the other entity set if the properties exist.
    • Interaction with Single Table Mode: If you use a SelectionVariant in multiple table mode, you can still apply single table mode views. However, if you use a UI.SelectionPresentationVariant, you cannot apply single table mode views.
    "RootEntityListReport": {
        "options": {
            "settings": {
                "views": {
                    "paths": [
                        {
                            "key": "tab1",
                            "annotationPath": "com.sap.vocabularies.UI.v1.SelectionVariant#variant1"
                        },
                        {
                            "key": "tab2",
                            "annotationPath": "com.sap.vocabularies.UI.v1.SelectionPresentationVariant#SelectionPresentationVariant"
                        },
                        {
                            "key": "tab3",
                            "entitySet": "OrganizationalUnits",
                            "annotationPath": "com.sap.vocabularies.UI.v1.SelectionVariant#activeOrgUnits"
                        }
                    ],
                    "showCounts": false
                }
            }
        }
    }