Samples / Controls / sap.f

Product Switch with Navigation

This sample demonstrates the navigation behavior of Product Switch, configurable by the app developer.

Class
z2ui5_cl_smpc_app_165
Repository
abap2UI5/samples-controls
Ports
sap.f.sample.ProductSwitchNavigation
UI5 libraries
sap.f, sap.m, sap.ui.core, sap.ui.layout
Lowest UI5 release
1.72
In the browser
Runs in the playground
Controls it builds
sap.f.ProductSwitch, sap.f.ProductSwitchItem, sap.m.Button, sap.m.ResponsivePopover, sap.m.Text, sap.ui.core.FragmentDefinition, sap.ui.core.mvc.View, sap.ui.layout.VerticalLayout

The class

" @keywords productswitch product switch sap.f productswitchnavigation verticallayout button text responsivepopover productswitchitem
" @summary This sample demonstrates the navigation behavior of Product Switch, configurable by the app developer.
" @origin sap.f.sample.ProductSwitchNavigation - https://sdk.openui5.org/entity/sap.f.ProductSwitch/sample/sap.f.sample.ProductSwitchNavigation (status: reviewed - read against the original, not run)
CLASS z2ui5_cl_smpc_app_165 DEFINITION PUBLIC.

  PUBLIC SECTION.
    INTERFACES z2ui5_if_app.

    TYPES:
      BEGIN OF ty_s_item,
        src       TYPE string,
        title     TYPE string,
        subtitle  TYPE string,
        targetsrc TYPE string,
        target    TYPE string,
      END OF ty_s_item.
    DATA t_items TYPE STANDARD TABLE OF ty_s_item WITH EMPTY KEY.

  PROTECTED SECTION.
    DATA client TYPE REF TO z2ui5_if_client.

    METHODS view_display.
    METHODS on_event.

    METHODS model_init.

  PRIVATE SECTION.
ENDCLASS.


CLASS z2ui5_cl_smpc_app_165 IMPLEMENTATION.

  METHOD z2ui5_if_app~main.

    me->client = client.
    IF client->check_on_init( ).
      model_init( ).
      view_display( ).
    ELSEIF client->check_on_navigated( ).
      view_display( ).
    ELSEIF client->check_on_event( ).
      on_event( ).
    ENDIF.

  ENDMETHOD.


  METHOD view_display.

    DATA(view) = z2ui5_cl_ui5_view_builder=>factory( ).

    " The ProductSwitch itself is built in the sample's controller (fnOpen) and
    " shown in a popover; the shipped view is just the trigger button plus two
    " explanatory texts, rebuilt 1:1 here. The press raises a backend event and
    " on_event builds the same popover - the older claim that there is no JS
    " controller so the press only toasts was refuted on 2026-08-05 and had
    " been left standing in this comment until 2026-08-23.
    view->ele( n = `View` ns = `mvc`
        )->a( n = `xmlns`     v = `sap.m`
        )->a( n = `xmlns:l`   v = `sap.ui.layout`
        )->a( n = `xmlns:mvc` v = `sap.ui.core.mvc`
        )->a( n = `height`    v = `100%`

        )->ele( n = `VerticalLayout` ns = `l`
            )->a( n = `class` v = `sapUiContentPadding`

            )->tag( `Button`
                )->a( n = `id`    v = `pSwitchBtn`
                )->a( n = `icon`  v = `sap-icon://menu`
                )->a( n = `text`  v = `Open Product Switch`
                " fnOpen loads ProductSwitchPopover.fragment.xml and opens it at this
                " button - rebuilt as a core:FragmentDefinition shown through
                " popover_display( by_id = ... ), the documented fragment-popover path
                )->a( n = `press` v = client->_event( `OPEN_SWITCH` )

            )->tag( `Text`
                )->a( n = `text` v = `Note: Redirection logic should be handled by the app developer.`

            )->tag( `Text`
                )->a( n = `text` v = `You can use sap.m.URLHelper, as shown in the fnChange method of the ProductSwitchNavigation controller.` ).

    client->view_display( view->stringify( ) ).

  ENDMETHOD.


  METHOD on_event.

    IF client->get_event( ) = `OPEN_SWITCH`.
      DATA(popover) = z2ui5_cl_ui5_view_builder=>factory( ).

      popover->ele( n = `FragmentDefinition` ns = `core`
          )->a( n = `xmlns`      v = `sap.m`
          )->a( n = `xmlns:f`    v = `sap.f`
          )->a( n = `xmlns:core` v = `sap.ui.core`

          )->ele( `ResponsivePopover`
              )->a( n = `placement`  v = `Bottom`
              )->a( n = `showHeader` v = `false`

              " fnOpen gives the popover an Emphasized Close endButton on a
              " phone only, wired to the controller's closing handler. The
              " branch stays a branch: the button is declared once and its
              " visibility bound to the device model, the form apps 030/089
              " use, and closing is the roundtrip-free popover_close action.
              )->ele( `endButton`
                  )->tag( `Button`
                      )->a( n = `text`    v = `Close`
                      )->a( n = `type`    v = `Emphasized`
                      )->a( n = `visible` v = |\{= $\{device>/system/phone\} \}|
                      )->a( n = `press`   v = client->follow_up_action( client->cs_event-popover_close )

              )->end(

              )->ele( n = `ProductSwitch` ns = `f`
                  )->a( n = `items`  v = client->_bind( t_items )
                  " fnChange toasts 'Redirecting to <targetSrc>' and calls
                  " URLHelper.redirect( targetSrc, true ) - both are client
                  " actions, chained on one event
                  )->a( n = `change` v = client->follow_up_action(
                            val   = client->cs_event-control_global
                            t_arg = VALUE #( ( `MESSAGE_TOAST` )
                                             ( `show` )
                                             ( `Redirecting to {0}` )
                                             ( `${$parameters>/itemPressed}.getTargetSrc()` ) ) ) && `; ` &&
                                        client->follow_up_action(
                            val   = client->cs_event-urlhelper
                            t_arg = VALUE #( ( `REDIRECT` )
                                             " a STRING TEMPLATE, not a backtick literal: only |...| treats
                                             " \{ as an escape. In a backtick literal the backslash is a real
                                             " character, the arg no longer starts with { , and get_t_arg
                                             " QUOTES the whole thing - the expression would never evaluate
                                             " and URLHelper would be handed a string with URL undefined
                                             ( |\{ URL: $\{$parameters>/itemPressed\}.getTargetSrc(), NEW_WINDOW: true \}| ) ) )

                  )->ele( n = `items` ns = `f`
                      )->tag( n = `ProductSwitchItem` ns = `f`
                          )->a( n = `src`       v = `{SRC}`
                          )->a( n = `title`     v = `{TITLE}`
                          )->a( n = `subTitle`  v = `{SUBTITLE}`
                          )->a( n = `targetSrc` v = `{TARGETSRC}`
                          )->a( n = `target`    v = `{TARGET}` ).

      client->popover_display( xml = popover->stringify( ) by_id = `pSwitchBtn` ).
    ENDIF.

  ENDMETHOD.


  METHOD model_init.

    " model/data.json, the three products the sample offers
    t_items = VALUE #(
      target = `_blank`
      ( src = `sap-icon://sap-logo-shape` title = `SAP Homepage` subtitle = `Learn more about SAP`
        targetsrc = `https://www.sap.com/index.html` )
      ( src = `sap-icon://newspaper` title = `Newsletter` subtitle = `Subscribe to receive the latest UI5 updates`
        targetsrc = `https://listserv.sap.com/mailman/listinfo/ui5.announce` )
      ( src = `sap-icon://group` title = `Community` subtitle = `Get involved`
        targetsrc = `https://community.sap.com/topics/ui5` ) ).

  ENDMETHOD.

ENDCLASS.