Single Planning Calendar with Multiple Date Selection
SinglePlanningCalendar with multiple date selection functionality.
Z2UI5_CL_SMPC_APP_109
Controls
sap.m
UI5 1.123
The facts
- Repository
- abap2UI5/samples-controls
- Class
Z2UI5_CL_SMPC_APP_109- Source file
z2ui5_cl_smpc_app_109.clas.abap↗- Library
- sap.m
- UI5 entity
sap.m.SinglePlanningCalendar- Demo kit sample
sap.m.sample.SinglePlanningCalendarDateSelection- SAP's own sample
- running at sdk.openui5.org ↗
- Minimum UI5
- 1.123
- In the playground
- runs in the browser, with no system and nothing installed
Keywords: singleplanningcalendar, single, planning, calendar, sap.m, day, selection, vbox, overflowtoolbar, toolbarseparator, label, togglebutton
Controls it builds
- sap.m.Label
- sap.m.OverflowToolbar
- sap.m.OverflowToolbarLayoutData
- sap.m.SinglePlanningCalendar
- sap.m.SinglePlanningCalendarDayView
- sap.m.SinglePlanningCalendarMonthView
- sap.m.SinglePlanningCalendarWeekView
- sap.m.SinglePlanningCalendarWorkWeekView
- sap.m.ToggleButton
- sap.m.ToolbarSeparator
- sap.m.VBox
- sap.ui.core.mvc.View
- sap.ui.unified.CalendarAppointment
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_109.clas.abap — 249 lines
Click a number to link to a line — shift-click for a range.
Read it on GitHub ↗
" @keywords singleplanningcalendar single planning calendar sap.m day selection vbox overflowtoolbar toolbarseparator label togglebutton
" @summary SinglePlanningCalendar with multiple date selection functionality.
CLASS z2ui5_cl_smpc_app_109 DEFINITION PUBLIC.
PUBLIC SECTION.
INTERFACES z2ui5_if_app.
" onPress flips the calendar's dateSelectionMode and swaps the button's
" tooltip - both are bindable properties, so they are held here and bound
" two-way rather than driven through a frontend action
DATA date_selection_mode TYPE string.
DATA multiselect_tooltip TYPE string.
TYPES: BEGIN OF ty_s_appointment,
title TYPE string,
text TYPE string,
type TYPE string,
icon TYPE string,
start_date TYPE string,
end_date TYPE string,
END OF ty_s_appointment.
DATA t_appointments TYPE STANDARD TABLE OF ty_s_appointment WITH EMPTY KEY.
DATA start_date TYPE string.
PROTECTED SECTION.
" one entry per DateRange the frontend marshalled out of the event's
" selectedDates parameter - startDate arrives as an ISO LOCAL timestamp
" (no Z), so its first ten characters are the day the user picked
TYPES: BEGIN OF ty_s_event_range,
startdate TYPE string,
END OF ty_s_event_range.
TYPES ty_t_event_range TYPE STANDARD TABLE OF ty_s_event_range WITH EMPTY KEY.
DATA client TYPE REF TO z2ui5_if_client.
METHODS view_display.
METHODS on_event.
METHODS event_ranges
IMPORTING
val TYPE string
RETURNING
VALUE(result) TYPE ty_t_event_range.
METHODS model_init.
PRIVATE SECTION.
ENDCLASS.
CLASS z2ui5_cl_smpc_app_109 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( ).
" startDate + CalendarAppointment startDate/endDate are object-typed: the model
" keeps ISO strings and Formatter.DateCreateObject converts them at the binding
view->ele( n = `View` ns = `mvc`
)->a( n = `xmlns:mvc` v = `sap.ui.core.mvc`
)->a( n = `xmlns:core` v = `sap.ui.core`
)->a( n = `xmlns:unified` v = `sap.ui.unified`
)->a( n = `xmlns` v = `sap.m`
)->a( n = `core:require` v = `{Formatter: 'z2ui5/model/formatter'}`
)->ele( `VBox`
)->a( n = `class` v = `sapUiSmallMargin`
)->ele( `OverflowToolbar`
)->a( n = `height` v = `100%`
)->a( n = `width` v = `100%`
)->tag( `ToolbarSeparator`
)->tag( `Label`
)->a( n = `text` v = `Day selection mode : `
)->ele( `ToggleButton`
)->a( n = `id` v = `MultiSelect`
)->a( n = `icon` v = `sap-icon://select-appointments`
)->a( n = `tooltip` v = client->_bind( multiselect_tooltip )
)->a( n = `press` v = client->_event( `PRESS` )
)->ele( `layoutData`
)->tag( `OverflowToolbarLayoutData`
)->a( n = `priority` v = `NeverOverflow`
)->end(
)->end(
)->end(
)->ele( `SinglePlanningCalendar`
)->a( n = `id` v = `SPC1`
)->a( n = `class` v = `sapUiSmallMarginTop`
)->a( n = `title` v = `My Calendar`
)->a( n = `dateSelectionMode` v = client->_bind( date_selection_mode )
)->a( n = `viewChange` v = client->_event( `VIEW_CHANGE` )
" the WHOLE selectedDates parameter travels in one arg: the
" frontend marshals each DateRange into its public properties
" (Lib.normalizeEventArgs), which is the loop the client
" expression grammar does not have
)->a( n = `selectedDatesChange` v = client->_event( val = `SELECTED_DATE` arg = `${$parameters>/selectedDates}` )
)->a( n = `weekNumberPress` v = client->_event( val = `WEEK` arg = `${$parameters>/weekNumber}` )
)->a( n = `startDateChange` v = client->_event( val = `START_DATE` arg = `${$parameters>/date}` )
)->a( n = `startDate` v = |\{ path: '{ client->_bind_path( start_date ) }', formatter: 'Formatter.DateCreateObject' \}|
)->a( n = `appointments` v = client->_bind( t_appointments )
)->ele( `views`
)->tag( `SinglePlanningCalendarDayView`
)->a( n = `key` v = `DayView`
)->a( n = `title` v = `Day`
)->tag( `SinglePlanningCalendarWorkWeekView`
)->a( n = `key` v = `WorkWeekView`
)->a( n = `title` v = `Work Week`
)->tag( `SinglePlanningCalendarWeekView`
)->a( n = `key` v = `WeekView`
)->a( n = `title` v = `Week`
)->tag( `SinglePlanningCalendarMonthView`
)->a( n = `key` v = `MonthView`
)->a( n = `title` v = `Month`
)->end(
)->ele( `appointments`
)->tag( n = `CalendarAppointment` ns = `unified`
)->a( n = `title` v = `{TITLE}`
)->a( n = `text` v = `{TEXT}`
)->a( n = `type` v = `{TYPE}`
)->a( n = `icon` v = `{ICON}`
)->a( n = `startDate` v = `{ path: 'START_DATE', formatter: 'Formatter.DateCreateObject' }`
)->a( n = `endDate` v = `{ path: 'END_DATE', formatter: 'Formatter.DateCreateObject' }` ).
client->view_display( view->stringify( ) ).
ENDMETHOD.
METHOD on_event.
CASE client->get_event( ).
WHEN `PRESS`.
" onPress: SingleSelect <-> MultiSelect, and the tooltip follows the
" pressed state exactly as the original's setTooltip does
IF date_selection_mode = `SingleSelect`.
date_selection_mode = `MultiSelect`.
multiselect_tooltip = `Disable multi-day selection`.
ELSE.
date_selection_mode = `SingleSelect`.
multiselect_tooltip = `Enable multi-day selection`.
ENDIF.
WHEN `VIEW_CHANGE`.
client->message_toast_display( |'viewChange' event fired.| ).
WHEN `SELECTED_DATE`.
" handleSelectedDateChange numbers every selected range and appends its
" start date, one per line - the array arrives marshalled, so the loop
" the original writes in JavaScript is an ABAP loop here
DATA(output) = ``.
DATA(ranges) = event_ranges( client->get_event_arg( ) ).
LOOP AT ranges REFERENCE INTO DATA(lr_range).
IF strlen( lr_range->startdate ) < 10.
CONTINUE.
ENDIF.
output = |{ output }{ sy-tabix }: { lr_range->startdate(10) }\n|.
ENDLOOP.
client->message_toast_display( |'selectedDatesChange' event fired.\n\nNew selected dates: \n{ output }| ).
WHEN `WEEK`.
" the original appends the pressed week number, which the event carries
client->message_toast_display( |'weekNumberPress' event fired.\n\nweek number is { client->get_event_arg( ) }| ).
WHEN `START_DATE`.
" same for the new start date (the event parameter, not a control ref)
client->message_toast_display( |'startDateChange' event fired.\n\nNew start date is { client->get_event_arg( ) }| ).
ENDCASE.
ENDMETHOD.
METHOD event_ranges.
DATA(lv_json) = condense( val ).
IF lv_json IS INITIAL.
RETURN.
ENDIF.
IF lv_json(1) <> `[`.
lv_json = |[{ lv_json }]|.
ENDIF.
TRY.
" a marshalled DateRange carries ALL its public properties (ID,
" startDate, endDate), so only the one field this port models is
" mapped - a plain to_abap( ) fails on the first extra one
"
" z2ui5_cl_ajson is the framework's VENDORED ajson copy and lives
" outside the released API (src/02), so it may be renamed or
" restructured without notice - the linter says so, and it is right.
" There is no released JSON reader to use instead, the same reasoning
" as apps 103 and 298; declared as a deviation in the sidecar
" abap2ui5lint-disable-next-line non-released-api -- no released JSON reader exists; see the comment above and the sidecar deviation
z2ui5_cl_ajson=>parse( lv_json
)->to_abap_corresponding_only(
)->to_abap( IMPORTING ev_container = result ).
" abap2ui5lint-disable-next-line non-released-api -- the exception of the call above
CATCH z2ui5_cx_ajson_error.
CLEAR result.
ENDTRY.
ENDMETHOD.
METHOD model_init.
" the calendar opens in single-day selection, and the button offers to
" enable the multi-day one - the original's view defaults
date_selection_mode = `SingleSelect`.
multiselect_tooltip = `Enable multi-day selection`.
start_date = `2018-07-09T00:00:00`.
t_appointments = VALUE #(
( title = `Discussion of the plan` text = `` type = `Type01` icon = `` start_date = `2018-07-09T00:00:00` end_date = `2018-07-09T00:00:00` )
( title = `Meet John Miller` text = `` type = `Type05` icon = `` start_date = `2018-07-08T05:00:00` end_date = `2018-07-08T06:00:00` )
( title = `Lunch` text = `canteen` type = `Type05` icon = `` start_date = `2018-07-08T07:00:00` end_date = `2018-07-08T08:00:00` )
( title = `New Product` text = `room 105` type = `Type01` icon = `sap-icon://meeting-room` start_date = `2018-07-08T08:00:00` end_date = `2018-07-08T09:00:00` )
( title = `Discussion with clients for the new release dates` text = `Online meeting` type = `Type08` icon = `` start_date = `2018-07-09T09:00:00` end_date = `2018-07-09T10:00:00` )
( title = `Meeting with the manager` text = `` type = `Type03` icon = `` start_date = `2018-07-06T09:00:00` end_date = `2018-07-06T10:00:00` )
( title = `Daily standup meeting` text = `` type = `Type01` icon = `` start_date = `2018-07-07T10:00:00` end_date = `2018-07-07T10:30:00` )
( title = `Private meeting` text = `` type = `Type03` icon = `` start_date = `2018-07-06T11:30:00` end_date = `2018-07-06T12:00:00` )
( title = `Lunch` text = `` type = `Type05` icon = `` start_date = `2018-07-06T12:00:00` end_date = `2018-07-06T13:00:00` )
( title = `Discussion of the plan` text = `` type = `Type01` icon = `` start_date = `2018-07-16T11:00:00` end_date = `2018-07-16T12:00:00` )
( title = `Lunch` text = `canteen` type = `Type05` icon = `` start_date = `2018-07-16T12:00:00` end_date = `2018-07-16T13:00:00` ) ).
ENDMETHOD.
ENDCLASS.
More in sap.m
- Select Dialog — The Select Dialog allows the user to search for and pick an item from a possibly long opt…
- Table Select Dialog — Similar to the Select Dialog, the Table Select Dialog presents selectable items in a tabl…
- Semantic Page Full Screen — Semantic Page Full Screen
- Semantic Page using Floating Footer — Integration of Floating Footer inside Semantic Page
- Semantic Page Master-Detail — Semantic Page Master/Detail
- Planning Calendar - without row header — PlanningCalendar with only one row without row header. On click on an interval a new appo…
- Upload Set — This sample shows an Upload Set control with a list of files to be uploaded and actions y…
- MaskInput — The sap.m.MaskInput control allows users to easily enter data in a certain format and in…
- Formatted Text — The control can be used for embedding formatted HTML text into your application.
- Check Box — Checkboxes allow users to select a subset of options. If you want to offer an off/on sett…
- Numeric Content of Different Colors — Shows NumericContent including numbers, units of measurement, and status arrows indicatin…
- Header Container - Vertical Mode — The Header Container with a vertical layout and with divider lines.
On this page