Dialog with Custom Footer
Dialog with custom footer and support for message popover.
Z2UI5_CL_SMPC_APP_562
Controls
sap.m
UI5 1.110
The facts
- Repository
- abap2UI5/samples-controls
- Class
Z2UI5_CL_SMPC_APP_562- Source file
z2ui5_cl_smpc_app_562.clas.abap↗- Library
- sap.m
- UI5 entity
sap.m.Dialog- Demo kit sample
sap.m.sample.DialogWithMessagePopover- SAP's own sample
- running at sdk.openui5.org ↗
- Minimum UI5
- 1.110
- In the playground
- runs in the browser, with no system and nothing installed
Keywords: dialog, sap.m, dialogwithmessagepopover, button, simpleform, title, label, input, columnelementdata, select, item, toolbar
Controls it builds
- sap.m.Button
- sap.m.Dialog
- sap.m.Input
- sap.m.Label
- sap.m.MessageItem
- sap.m.MessagePopover
- sap.m.Page
- sap.m.Select
- sap.m.Toolbar
- sap.m.ToolbarSpacer
- sap.m.VBox
- sap.ui.core.FragmentDefinition
- sap.ui.core.Item
- sap.ui.core.Title
- sap.ui.core.mvc.View
- sap.ui.layout.form.ColumnElementData
- sap.ui.layout.form.SimpleForm
- z2ui5.cc.MessageManager
Read out of the builder chain by the abap2UI5 linter, not from the category this sample is filed under — which is what makes “which samples build one of these” a question the catalogue can answer at all.
Libraries
Run it here
The sample running, in this page — the app on its own, with no editor over it.
Switch to Playground with this code
Nothing is installed and nothing is sent anywhere: the ABAP is compiled to JavaScript in this browser and runs against abap2UI5 itself.
The ABAP
z2ui5_cl_smpc_app_562.clas.abap — 493 lines
Click a number to link to a line — shift-click for a range.
Read it on GitHub ↗
" @keywords dialog sap.m dialogwithmessagepopover button simpleform title label input columnelementdata select item toolbar
" @summary Dialog with custom footer and support for message popover.
CLASS z2ui5_cl_smpc_app_562 DEFINITION PUBLIC.
PUBLIC SECTION.
INTERFACES z2ui5_if_app.
TYPES:
BEGIN OF ty_s_form,
name TYPE string,
street_name TYPE string,
street_number TYPE string,
zip_code TYPE string,
zip_city TYPE string,
country TYPE string,
email TYPE string,
phone_number TYPE string,
phone_time TYPE string,
website TYPE string,
END OF ty_s_form.
TYPES:
BEGIN OF ty_s_employment,
jobtitle TYPE string,
paygrade TYPE string,
unit TYPE string,
class TYPE string,
fte TYPE string,
weeklyhours TYPE string,
END OF ty_s_employment.
TYPES:
BEGIN OF ty_s_message,
message TYPE string,
description TYPE string,
type TYPE string,
target TYPE string,
additionaltext TYPE string,
code TYPE string,
END OF ty_s_message.
DATA t_forms TYPE STANDARD TABLE OF ty_s_form WITH EMPTY KEY.
DATA t_employment TYPE STANDARD TABLE OF ty_s_employment WITH EMPTY KEY.
DATA t_messages TYPE STANDARD TABLE OF ty_s_message WITH EMPTY KEY.
" the fragment's title is `Hello {/recipient/name}` - the shared demo kit
" forms.json carries no `recipient` node at all, so the original renders a
" bare `Hello `; the empty field keeps that 1:1
DATA recipient_name TYPE string.
" buttonIconFormatter / buttonTypeFormatter / highestSeverityMessages
DATA btn_icon TYPE string.
DATA btn_type TYPE string VALUE `Default`.
DATA btn_text TYPE string.
PROTECTED SECTION.
DATA client TYPE REF TO z2ui5_if_client.
METHODS view_display.
METHODS popup_dialog_display.
METHODS on_event.
METHODS model_init.
METHODS button_severity_set.
PRIVATE SECTION.
ENDCLASS.
CLASS z2ui5_cl_smpc_app_562 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( ).
view->ele( n = `View` ns = `mvc`
)->a( n = `height` v = `100%`
)->a( n = `xmlns` v = `sap.m`
)->a( n = `xmlns:mvc` v = `sap.ui.core.mvc`
)->ele( `Page`
)->a( n = `id` v = `messageHandlingPage`
)->a( n = `showHeader` v = `false`
)->tag( `Button`
)->a( n = `text` v = `Open Dialog With Message Popover`
)->a( n = `class` v = `sapUiMediumMargin`
)->a( n = `ariaHasPopup` v = `Dialog`
)->a( n = `press` v = client->_event( `OPEN_DIALOG` )
)->end( ).
client->view_display( view->stringify( ) ).
ENDMETHOD.
METHOD popup_dialog_display.
DATA(popup) = z2ui5_cl_ui5_view_builder=>factory( ).
DATA(dialog) = popup->ele( n = `FragmentDefinition` ns = `core`
)->a( n = `xmlns` v = `sap.m`
)->a( n = `xmlns:f` v = `sap.ui.layout.form`
)->a( n = `xmlns:mvc` v = `sap.ui.core.mvc`
)->a( n = `xmlns:core` v = `sap.ui.core`
)->a( n = `xmlns:z2ui5` v = `z2ui5.cc`
)->ele( `Dialog`
)->a( n = `id` v = `mainDialog`
)->a( n = `title` v = |Hello { client->_bind( recipient_name ) }| ).
DATA(content) = dialog->ele( `content` ).
content->ele( `VBox`
)->a( n = `id` v = `formContainer`
)->a( n = `class` v = `sapUiSmallMargin`
)->a( n = `items` v = client->_bind( t_forms )
)->ele( n = `SimpleForm` ns = `f`
)->a( n = `id` v = `SimpleFormChangeColumn_twoGroups234`
)->a( n = `editable` v = `true`
)->a( n = `layout` v = `ColumnLayout`
)->a( n = `title` v = `Personal`
)->a( n = `columnsM` v = `2`
)->a( n = `columnsL` v = `2`
)->a( n = `columnsXL` v = `2`
)->ele( n = `content` ns = `f`
)->tag( n = `Title` ns = `core`
)->a( n = `text` v = `Information`
)->tag( `Label`
)->a( n = `text` v = `Name`
)->tag( `Input`
)->a( n = `required` v = `true`
)->a( n = `value` v = `{ path: 'NAME', type: 'sap.ui.model.type.String' }`
)->a( n = `change` v = client->_event( `CHANGE` )
)->tag( `Label`
)->a( n = `text` v = `Street/No.`
)->tag( `Input`
)->a( n = `value` v = `{STREET_NAME}`
)->ele( `Input`
)->a( n = `value` v = `{STREET_NUMBER}`
)->ele( `layoutData`
)->tag( n = `ColumnElementData` ns = `f`
)->a( n = `cellsSmall` v = `2`
)->a( n = `cellsLarge` v = `2`
)->end(
)->end(
)->tag( `Label`
)->a( n = `text` v = `ZIP Code/City`
)->ele( `Input`
)->a( n = `value` v = `{ path: 'ZIP_CODE', type: 'sap.ui.model.type.Integer' }`
)->ele( `layoutData`
)->tag( n = `ColumnElementData` ns = `f`
)->a( n = `cellsSmall` v = `3`
)->a( n = `cellsLarge` v = `2`
)->end(
)->end(
)->tag( `Input`
)->a( n = `value` v = `{ZIP_CITY}`
)->tag( `Label`
)->a( n = `text` v = `Country`
)->ele( `Select`
)->a( n = `id` v = `country`
)->a( n = `selectedKey` v = `{COUNTRY}`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `England`
)->a( n = `text` v = `England`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `Germany`
)->a( n = `text` v = `Germany`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `USA`
)->a( n = `text` v = `USA`
)->end(
)->tag( n = `Title` ns = `core`
)->a( n = `text` v = `Contact`
)->tag( `Label`
)->a( n = `text` v = `Email`
)->tag( `Input`
)->a( n = `value` v = `{ path: 'EMAIL', type: 'sap.ui.model.type.String', constraints: { search: '^\\w+[\\w-+\\.]*\\@[a-zA-Z]+.[a-zA-Z]+' } }`
)->tag( `Label`
)->a( n = `text` v = `Phone Number`
)->tag( `Input`
)->a( n = `value` v = `{PHONE_NUMBER}`
)->ele( `Input`
)->a( n = `value` v = `{PHONE_TIME}`
)->ele( `layoutData`
)->tag( n = `ColumnElementData` ns = `f`
)->a( n = `cellsSmall` v = `2`
)->a( n = `cellsLarge` v = `2`
)->end(
)->end(
)->tag( `Label`
)->a( n = `text` v = `Personal website`
)->tag( `Input`
)->a( n = `value` v = `{WEBSITE}`
)->end(
)->end(
)->end( ).
content->ele( `VBox`
)->a( n = `id` v = `formContainerEmployment`
)->a( n = `class` v = `sapUiSmallMargin`
)->a( n = `items` v = client->_bind( t_employment )
)->ele( n = `SimpleForm` ns = `f`
)->a( n = `editable` v = `true`
)->a( n = `layout` v = `ColumnLayout`
)->a( n = `title` v = `Personal`
)->a( n = `columnsM` v = `2`
)->a( n = `columnsL` v = `2`
)->a( n = `columnsXL` v = `2`
)->ele( n = `content` ns = `f`
)->tag( n = `Title` ns = `core`
)->a( n = `text` v = `Information`
)->tag( `Label`
)->a( n = `text` v = `Job Classification`
)->tag( `Input`
)->a( n = `value` v = `{JOBTITLE}`
)->tag( `Label`
)->a( n = `text` v = `Pay Grade`
)->tag( `Input`
)->a( n = `value` v = `{PAYGRADE}`
)->tag( `Label`
)->a( n = `text` v = `Unit`
)->tag( `Input`
)->a( n = `value` v = `{UNIT}`
)->tag( n = `Title` ns = `core`
)->a( n = `text` v = `Rating`
)->tag( `Label`
)->a( n = `text` v = `Employee Class`
)->tag( `Input`
)->a( n = `value` v = `{CLASS}`
)->tag( `Label`
)->a( n = `text` v = `FTE`
)->tag( `Input`
)->a( n = `value` v = `{FTE}`
)->tag( `Label`
)->a( n = `text` v = `Standard Weekly Hours`
)->tag( `Input`
)->a( n = `value` v = `{ path: 'WEEKLYHOURS', type: 'sap.ui.model.type.Integer', constraints: { maximum: 40 } }`
)->a( n = `change` v = client->_event( `CHANGE` )
)->end(
)->end(
)->end( ).
" abap2UI5 feeds app-authored messages into the message manager through this
" companion control (app 065 idiom) - the original calls Messaging.addMessages
content->tag( n = `MessageManager` ns = `z2ui5`
)->a( n = `items` v = client->_bind( t_messages ) ).
dialog->ele( `footer`
)->ele( `Toolbar`
)->ele( `content`
)->ele( `Button`
)->a( n = `id` v = `messagePopoverBtn`
)->a( n = `visible` v = |\{= !!$\{message>/\}.length \}|
)->a( n = `icon` v = client->_bind( btn_icon )
)->a( n = `type` v = client->_bind( btn_type )
)->a( n = `text` v = client->_bind( btn_text )
)->a( n = `ariaHasPopup` v = `Dialog`
" handleMessagePopoverPress: this.oMP.toggle(oEvent.getSource()) - a pure
" client-side toggle, so wired roundtrip-free onto the button's own id
)->a( n = `press` v = client->follow_up_action( val = client->cs_event-control_by_id
t_arg = VALUE #( ( `messagePopover` ) ( `toggleBy` ) ( `messagePopoverBtn` ) ) )
)->ele( `dependents`
)->ele( `MessagePopover`
)->a( n = `id` v = `messagePopover`
)->a( n = `items` v = `{message>/}`
)->a( n = `groupItems` v = `true`
" activeTitlePress ships the pressed message's target control id so
" the handler can scroll to it and focus it
)->a( n = `activeTitlePress` v = client->_event( val = `ACTIVE_TITLE` arg = `${$parameters>/item}.getBindingContext('message').getObject().getControlIds()[0]` )
)->tag( `MessageItem`
)->a( n = `title` v = `{message>message}`
)->a( n = `subtitle` v = `{message>additionalText}`
)->a( n = `type` v = `{message>type}`
)->a( n = `description` v = `{message>message}`
)->a( n = `activeTitle` v = `true`
" getGroupName reads the form titles around the target control -
" a domain classification, so it is computed in the backend and
" rides on the Message code field (see model below)
)->a( n = `groupName` v = `{message>code}`
)->end(
)->end(
)->end(
)->tag( `ToolbarSpacer`
)->tag( `Button`
)->a( n = `type` v = `Accept`
)->a( n = `text` v = `Save`
)->a( n = `press` v = client->_event( `SAVE` )
)->tag( `Button`
)->a( n = `id` v = `Reject`
)->a( n = `text` v = `Reject`
)->a( n = `type` v = `Reject`
)->a( n = `ariaHasPopup` v = `Dialog`
)->a( n = `press` v = client->_event( `CLOSE_DIALOG` )
)->end(
)->end(
)->end( ).
client->popup_display( popup->stringify( ) ).
ENDMETHOD.
METHOD on_event.
CASE client->get_event( ).
WHEN `OPEN_DIALOG`.
popup_dialog_display( ).
client->message_toast_display( `Press "Save" to trigger validation.` ).
WHEN `CLOSE_DIALOG`.
client->popup_destroy( ).
WHEN `ACTIVE_TITLE`.
" activeTitlePress scrolls to the message's target control, closes the popover
" and focuses the control; the full control id travels from the pressed
" MessageItem's message object (getControlIds()[0])
DATA(control_id) = client->get_event_arg( ).
IF control_id IS NOT INITIAL.
client->follow_up_action( val = client->cs_event-scroll_into_view
t_arg = VALUE #( ( control_id ) ) ).
client->follow_up_action( val = client->cs_event-control_by_id
t_arg = VALUE #( ( `messagePopover` ) ( `close` ) ) ).
client->follow_up_action( val = client->cs_event-set_focus
t_arg = VALUE #( ( control_id ) ) ).
ENDIF.
WHEN `SAVE`.
" _generateInvalidUserInput(): force a set of fields invalid to demo the
" message handling, then open the MessagePopover. abap2UI5 only auto-collects
" validation messages from USER input, not from programmatically-set model
" values, so Save mirrors the issues explicitly on the SAME rows the original
" reaches through formContainer.getItems()[4/5/6] - John Miller / Stefan Bosch
" / Maria Fontes - plus the employment row, and authors the matching messages
IF lines( t_forms ) >= 7.
t_forms[ 5 ]-name = ``.
t_forms[ 6 ]-zip_code = `AAA`.
t_forms[ 7 ]-email = `MariaFontes.com`.
ENDIF.
IF t_employment IS NOT INITIAL.
t_employment[ 1 ]-weeklyhours = `400`.
ENDIF.
" the group name is `<form title>, <group title>`: the Personal form's
" Information and Contact groups, and the employment form's Rating group
" (Standard Weekly Hours sits there in this sample)
t_messages = VALUE #(
( message = `A mandatory field is required` type = `Error` additionaltext = `Name`
target = `/T_FORMS/4/NAME` code = `Personal, Information` )
( message = `Enter a number without decimals.` type = `Error` additionaltext = `ZIP Code/City`
target = `/T_FORMS/5/ZIP_CODE` code = `Personal, Information` )
( message = `Enter a valid email address.` type = `Error` additionaltext = `Email`
target = `/T_FORMS/6/EMAIL` code = `Personal, Contact` )
( message = `The value should not exceed 40` type = `Warning` additionaltext = `Standard Weekly Hours`
description = `The value of the working hours field should not exceed 40 hours.`
target = `/T_EMPLOYMENT/0/WEEKLYHOURS` code = `Personal, Rating` ) ).
button_severity_set( ).
" the binding-change handler navigates the popover back and refreshes the
" button, then oMP.openBy(oButton) opens it anchored to the button
client->follow_up_action( val = client->cs_event-control_by_id
t_arg = VALUE #( ( `messagePopover` ) ( `openBy` ) ( `messagePopoverBtn` ) ) ).
WHEN `CHANGE`.
" onChange manually adds/removes the required-field and constraint messages;
" here the typed bindings with constraints collect those AUTOMATICALLY into
" the message> model (no app code), so the handler only pushes the model back
ENDCASE.
ENDMETHOD.
METHOD button_severity_set.
" buttonTypeFormatter / buttonIconFormatter: Error > Warning > Success > Info
CLEAR btn_icon.
CLEAR btn_type.
LOOP AT t_messages INTO DATA(msg).
CASE msg-type.
WHEN `Error`.
btn_type = `Negative`.
btn_icon = `sap-icon://error`.
WHEN `Warning`.
IF btn_type <> `Negative`.
btn_type = `Critical`.
ENDIF.
IF btn_icon <> `sap-icon://error`.
btn_icon = `sap-icon://alert`.
ENDIF.
WHEN `Success`.
IF btn_type <> `Negative` AND btn_type <> `Critical`.
btn_type = `Success`.
ENDIF.
IF btn_icon <> `sap-icon://error` AND btn_icon <> `sap-icon://alert`.
btn_icon = `sap-icon://sys-enter-2`.
ENDIF.
WHEN OTHERS.
IF btn_type IS INITIAL.
btn_type = `Neutral`.
ENDIF.
IF btn_icon IS INITIAL.
btn_icon = `sap-icon://information`.
ENDIF.
ENDCASE.
ENDLOOP.
" highestSeverityMessages: how many messages carry the highest severity found
DATA(highest) = SWITCH string( btn_type
WHEN `Negative` THEN `Error`
WHEN `Critical` THEN `Warning`
WHEN `Success` THEN `Success`
ELSE `Information` ).
DATA(count) = REDUCE i( INIT n = 0 FOR m IN t_messages NEXT n = COND #( WHEN m-type = highest THEN n + 1 ELSE n ) ).
btn_text = COND #( WHEN count = 0 THEN `` ELSE |{ count }| ).
" the formatter returns undefined while no message carries a severity; an empty
" string would override the enum DEFAULT and reject the whole view
IF btn_type IS INITIAL.
btn_type = `Default`.
ENDIF.
ENDMETHOD.
METHOD model_init.
" the shared demo kit forms.json - all 8 forms and the single employment row
t_forms = VALUE #(
( name = `Julie Armstrong` street_name = `Mainstreet` street_number = `1278`
zip_code = `12345` zip_city = `Maintown` country = `Germany`
email = `Julie.Armstrong@company.com` phone_number = `+1 (610) 661-1000` phone_time = `12:00` website = `n/a` )
( name = `Denise Smith` street_name = `Mainstreet` street_number = `1567`
zip_code = `12345` zip_city = `Maintown` country = `Germany`
email = `Denise.Smith@company.com` phone_number = `+1 (610) 661-1000` phone_time = `12:00` website = `n/a` )
( name = `Richard Wilson` street_name = `Mainstreet` street_number = `2984`
zip_code = `12345` zip_city = `Maintown` country = `Germany`
email = `Richard.Wilson@company.com` phone_number = `+1 (610) 661-1000` phone_time = `12:00` website = `n/a` )
( name = `Gerd Becker` street_name = `Mainstreet` street_number = `3614`
zip_code = `12345` zip_city = `Maintown` country = `Germany`
email = `Gerd.Becker@company.com` phone_number = `+1 (610) 661-1000` phone_time = `12:00` website = `n/a` )
( name = `John Miller` street_name = `Mainstreet` street_number = `1618`
zip_code = `AAA` zip_city = `Maintown` country = `Germany`
email = `John.Miller@company.com` phone_number = `+1 (610) 661-1000` phone_time = `12:00` website = `n/a` )
( name = `Stefan Bosch` street_name = `Mainstreet` street_number = `4864`
zip_code = `12345` zip_city = `Maintown` country = `Germany`
email = `Stefan.Bosch@company.com` phone_number = `+1 (610) 661-1000` phone_time = `12:00` website = `n/a` )
( name = `Maria Fontes` street_name = `Mainstreet` street_number = `4864`
zip_code = `12345` zip_city = `Maintown` country = `Germany`
email = `` phone_number = `+1 (610) 661-1000` phone_time = `12:00` website = `MariaFontescompany.com` )
( name = `Antonio Ferrari` street_name = `Mainstreet` street_number = `2598`
zip_code = `12345` zip_city = `Maintown` country = `Germany`
email = `Antonio.Ferrari@company.com` phone_number = `+1 (610) 661-1000` phone_time = `12:00` website = `n/a` ) ).
t_employment = VALUE #(
( jobtitle = `Senior UI Developer (UIDEV-SR)` paygrade = `Salary Grade 18 (GR-14`
unit = `ABC` class = `Employee` fte = `1` weeklyhours = `0` ) ).
ENDMETHOD.
ENDCLASS.
More in sap.m
- Single Planning Calendar with Zoom In and Zoom Out behavior — SinglePlanningCalendar with enabled Zoom In and Zoom Out functionality.
- Single Planning Calendar with Recurring Calendar Items — SinglePlanningCalendar with recurring calendar items
- Date Picker Mass Editing Scenario — Using calendar in a dialog for changing dates in mass editing scenario.
- Facet Filter - Custom Filters — With the FacetFilter you can define custom filtering criteria to be applied when searchin…
- Tab Container - Multi-instance handling concept — Allows detail view / edit in sap.m.TabContainer after selecting items from table.
- Dialog in Custom Within Area — Within area of sap.ui.core.Popup determines where all popups (including dialogs) are posi…
- Message View inside Popover — A sample with Message View inside a Popover.
- Message View inside ResponsivePopover — A sample with Message View inside a ResponsivePopover.
- Popover with NavContainer — You can nest NavContainers in Popovers (and Dialogs) to navigate to further details in pl…
- Table - Breadcrumb — With an InfoToolbar and some crumb logic you can navigate simple hierarchies with a bread…
- Table - Defining Column Width — While defining the column width you can use percent values but you should be careful with…
- Table - ContextualWidth (Static) — This example shows the container-based pop-in behavior. The container has static width.
On this page