Single Planning Calendar with Recurring Calendar Items
SinglePlanningCalendar with recurring calendar items
Z2UI5_CL_SMPC_APP_555
Controls
sap.m
UI5 1.149
The facts
- Repository
- abap2UI5/samples-controls
- Class
Z2UI5_CL_SMPC_APP_555- Source file
z2ui5_cl_smpc_app_555.clas.abap↗- Library
- sap.m
- UI5 entity
sap.m.SinglePlanningCalendar- Demo kit sample
sap.m.sample.SinglePlanningCalendarRecurringItem- SAP's own sample
- running at sdk.openui5.org ↗
- Minimum UI5
- 1.149
- In the playground
- runs in the browser, with no system and nothing installed
Keywords: singleplanningcalendar, single, planning, calendar, sap.m, singleplanningcalendarrecurringitem, vbox, overflowtoolbar, button, toolbarseparator, recurringnonworkingperiod, timerange
Controls it builds
- sap.m.Button
- sap.m.DatePicker
- sap.m.DateTimePicker
- sap.m.Dialog
- sap.m.HBox
- sap.m.Input
- sap.m.Label
- sap.m.MultiComboBox
- sap.m.OverflowToolbar
- sap.m.Select
- sap.m.SinglePlanningCalendar
- sap.m.SinglePlanningCalendarDayView
- sap.m.SinglePlanningCalendarMonthView
- sap.m.SinglePlanningCalendarWeekView
- sap.m.SinglePlanningCalendarWorkWeekView
- sap.m.Text
- sap.m.ToolbarSeparator
- sap.m.VBox
- sap.ui.core.CustomData
- sap.ui.core.FragmentDefinition
- sap.ui.core.Item
- sap.ui.core.Title
- sap.ui.core.mvc.View
- sap.ui.layout.form.SimpleForm
- sap.ui.unified.RecurrenceRule
- sap.ui.unified.RecurringCalendarAppointment
- sap.ui.unified.RecurringNonWorkingPeriod
- sap.ui.unified.TimeRange
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_555.clas.abap — 716 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 singleplanningcalendarrecurringitem vbox overflowtoolbar button toolbarseparator recurringnonworkingperiod timerange
" @summary SinglePlanningCalendar with recurring calendar items
CLASS z2ui5_cl_smpc_app_555 DEFINITION PUBLIC.
PUBLIC SECTION.
INTERFACES z2ui5_if_app.
" RecurrenceRule.days is an int[]: a table of STRINGS serializes to ['1','2']
" and UI5 rejects it, so the day tables are integer tables
TYPES ty_t_int TYPE STANDARD TABLE OF i WITH EMPTY KEY.
TYPES: BEGIN OF ty_s_appointment,
start_at TYPE string,
end_at TYPE string,
title TYPE string,
text TYPE string,
type TYPE string,
recurrencetype TYPE string,
recurrencepattern TYPE i,
recurrenceenddate TYPE string,
t_recurrence_day TYPE ty_t_int,
ruletype TYPE string,
ruledayofmonth TYPE i,
ruleweekofmonth TYPE string,
ruledayofweek TYPE i,
rulemonth TYPE i,
END OF ty_s_appointment.
TYPES ty_t_appointment TYPE STANDARD TABLE OF ty_s_appointment WITH EMPTY KEY.
TYPES: BEGIN OF ty_s_non_working,
date_at TYPE string,
start_at TYPE string,
end_at TYPE string,
valueformat TYPE string,
title TYPE string,
recurrencetype TYPE string,
recurrencepattern TYPE i,
recurrenceenddate TYPE string,
t_recurrence_day TYPE ty_t_int,
END OF ty_s_non_working.
TYPES ty_t_non_working TYPE STANDARD TABLE OF ty_s_non_working WITH EMPTY KEY.
DATA t_appointments TYPE ty_t_appointment.
DATA t_non_working TYPE ty_t_non_working.
DATA start_date TYPE string.
" the create dialog's own model, folded to fields (see sidecar)
DATA c_title TYPE string.
DATA c_text TYPE string.
DATA c_type TYPE string.
DATA c_start TYPE string.
DATA c_end TYPE string.
DATA c_rec_type TYPE string.
DATA c_rec_pattern TYPE string.
DATA c_rec_days TYPE string_table.
DATA c_rec_end TYPE string.
DATA c_rule_type TYPE string.
DATA c_rule_dom TYPE string.
DATA c_rule_wom TYPE string.
DATA c_rule_dow TYPE string.
DATA c_rule_month TYPE string.
PROTECTED SECTION.
DATA client TYPE REF TO z2ui5_if_client.
METHODS view_display.
METHODS on_event.
METHODS popup_create_display.
METHODS create_reset.
METHODS model_init.
PRIVATE SECTION.
ENDCLASS.
CLASS z2ui5_cl_smpc_app_555 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 calendar date properties are typed "object" and demand a real JS Date;
" the model keeps ISO strings and Formatter.DateCreateObject converts them
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( `Button`
)->a( n = `text` v = `Create Appointment`
)->a( n = `icon` v = `sap-icon://add-activity`
)->a( n = `press` v = client->_event( `CREATE_APPOINTMENT` )
)->a( n = `type` v = `Emphasized`
)->tag( `ToolbarSeparator`
)->end(
)->ele( `SinglePlanningCalendar`
)->a( n = `id` v = `SPC1`
)->a( n = `class` v = `sapUiSmallMarginTop`
)->a( n = `title` v = `My Calendar`
" handleViewChange only toasts a constant text - composed on the client
)->a( n = `viewChange` v = client->follow_up_action(
val = client->cs_event-control_global
t_arg = VALUE #( ( `MESSAGE_TOAST` ) ( `show` ) ( `'viewChange' event fired.` ) ) )
)->a( n = `startDate` v = |\{ path: '{ client->_bind_path( start_date ) }', formatter: 'Formatter.DateCreateObject' \}|
" ROOT-level aggregations: the path has to be the model path
" client->_bind_path( ) resolves to. A bare 'T_' is
" RELATIVE, which is right only inside a row-bound aggregation
" (apps 536/545 bind their rows' tables that way) - here it
" resolved against nothing and the calendar came up with zero
" appointments (e2e-caught 2026-08-22)
)->a( n = `nonWorkingPeriods` v = |\{ path: '{ client->_bind_path( t_non_working ) }', templateShareable: false \}|
)->a( n = `appointments` v = |\{ path: '{ client->_bind_path( t_appointments ) }', templateShareable: false \}|
)->ele( `nonWorkingPeriods`
)->ele( n = `RecurringNonWorkingPeriod` ns = `unified`
)->a( n = `date` v = `{ path: 'DATE_AT', formatter: 'Formatter.DateCreateObject' }`
)->a( n = `recurrenceType` v = |\{= $\{RECURRENCETYPE\} \|\| null \}|
" setRecurrencePattern raises "recurrencePattern must be >= 1" here too,
" and no ABAP writes a non-working row - the appointments get their 1
" from CREATE_SAVE, these get it from the binding (see sidecar)
)->a( n = `recurrencePattern` v = `{= ${RECURRENCEPATTERN} || 1 }`
)->a( n = `recurrenceEndDate` v = `{ path: 'RECURRENCEENDDATE', formatter: 'Formatter.DateCreateObject' }`
)->ele( n = `timeRange` ns = `unified`
)->tag( n = `TimeRange` ns = `unified`
)->a( n = `start` v = `{START_AT}`
)->a( n = `end` v = `{END_AT}`
)->a( n = `valueFormat` v = `{VALUEFORMAT}`
)->end(
)->ele( n = `recurrenceRule` ns = `unified`
)->tag( n = `RecurrenceRule` ns = `unified`
)->a( n = `days` v = `{T_RECURRENCE_DAY}`
)->end(
)->end(
)->end(
)->ele( `appointments`
)->ele( n = `RecurringCalendarAppointment` ns = `unified`
)->a( n = `startDate` v = `{ path: 'START_AT', formatter: 'Formatter.DateCreateObject' }`
)->a( n = `endDate` v = `{ path: 'END_AT', formatter: 'Formatter.DateCreateObject' }`
)->a( n = `title` v = `{TITLE}`
)->a( n = `text` v = `{TEXT}`
)->a( n = `type` v = `{TYPE}`
)->a( n = `recurrenceType` v = |\{= $\{RECURRENCETYPE\} \|\| null \}|
)->a( n = `recurrencePattern` v = `{RECURRENCEPATTERN}`
)->a( n = `recurrenceEndDate` v = `{ path: 'RECURRENCEENDDATE', formatter: 'Formatter.DateCreateObject' }`
)->ele( n = `recurrenceRule` ns = `unified`
)->tag( n = `RecurrenceRule` ns = `unified`
)->a( n = `days` v = `{T_RECURRENCE_DAY}`
)->a( n = `type` v = |\{= $\{RULETYPE\} \|\| null \}|
)->a( n = `dayOfMonth` v = `{RULEDAYOFMONTH}`
)->a( n = `weekOfMonth` v = |\{= $\{RULEWEEKOFMONTH\} \|\| null \}|
)->a( n = `dayOfWeek` v = `{RULEDAYOFWEEK}`
)->a( n = `month` v = `{RULEMONTH}`
)->end(
)->end(
)->end(
)->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` ).
client->view_display( view->stringify( ) ).
ENDMETHOD.
METHOD popup_create_display.
DATA(popup) = z2ui5_cl_ui5_view_builder=>factory( ).
popup->ele( n = `FragmentDefinition` ns = `core`
)->a( n = `xmlns` v = `sap.m`
)->a( n = `xmlns:core` v = `sap.ui.core`
)->a( n = `xmlns:form` v = `sap.ui.layout.form`
)->ele( `Dialog`
)->a( n = `title` v = `Create Appointment`
)->a( n = `contentWidth` v = `500px`
)->ele( `customData`
)->tag( n = `CustomData` ns = `core`
)->a( n = `key` v = `model`
)->end(
)->ele( `content`
)->ele( n = `SimpleForm` ns = `form`
)->a( n = `editable` v = `true`
)->a( n = `layout` v = `ResponsiveGridLayout`
)->a( n = `labelSpanXL` v = `4`
)->a( n = `labelSpanL` v = `4`
)->a( n = `labelSpanM` v = `4`
)->a( n = `labelSpanS` v = `12`
)->a( n = `emptySpanXL` v = `0`
)->a( n = `emptySpanL` v = `0`
)->a( n = `emptySpanM` v = `0`
)->a( n = `columnsXL` v = `1`
)->a( n = `columnsL` v = `1`
)->a( n = `columnsM` v = `1`
)->tag( n = `Title` ns = `core`
)->a( n = `text` v = `General`
)->tag( `Label`
)->a( n = `text` v = `Title`
)->a( n = `required` v = `true`
)->tag( `Input`
)->a( n = `value` v = client->_bind( c_title )
)->a( n = `placeholder` v = `Appointment title`
)->tag( `Label`
)->a( n = `text` v = `Description`
)->tag( `Input`
)->a( n = `value` v = client->_bind( c_text )
)->a( n = `placeholder` v = `Optional description`
)->tag( `Label`
)->a( n = `text` v = `Type`
)->ele( `Select`
)->a( n = `selectedKey` v = client->_bind( c_type )
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `Type01`
)->a( n = `text` v = `Type 01`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `Type02`
)->a( n = `text` v = `Type 02`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `Type03`
)->a( n = `text` v = `Type 03`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `Type04`
)->a( n = `text` v = `Type 04`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `Type05`
)->a( n = `text` v = `Type 05`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `Type06`
)->a( n = `text` v = `Type 06`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `Type07`
)->a( n = `text` v = `Type 07`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `Type08`
)->a( n = `text` v = `Type 08`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `Type09`
)->a( n = `text` v = `Type 09`
)->end(
)->tag( n = `Title` ns = `core`
)->a( n = `text` v = `Date & Time`
)->tag( `Label`
)->a( n = `text` v = `Start`
)->tag( `DateTimePicker`
" The ORIGINAL binds this typed, with a pattern:
" type: 'sap.ui.model.type.DateTime',
" formatOptions: \{ pattern: 'yyyy-MM-dd HH:mm' \}
" The port kept the path and dropped both, so the picker wrote a
" LOCALE string back. Measured in de-DE: the user picks 4 March
" 2025, the model stores "04.03.2025, 10:15:00", and
" Formatter.DateCreateObject's new Date( ) reads it MONTH-first -
" the appointment is drawn on 3 April. valueFormat rather than the
" typed binding because this field seeds EMPTY on the recurrence
" picker, and a typed binding with a source pattern raises on the
" empty value a cleared picker sends (the app-549/609 reasoning)
)->a( n = `valueFormat` v = `yyyy-MM-dd'T'HH:mm:ss`
)->a( n = `displayFormat` v = `yyyy-MM-dd HH:mm`
)->a( n = `value` v = client->_bind( c_start )
)->tag( `Label`
)->a( n = `text` v = `End`
)->tag( `DateTimePicker`
" see the Start picker above - same contract
)->a( n = `valueFormat` v = `yyyy-MM-dd'T'HH:mm:ss`
)->a( n = `displayFormat` v = `yyyy-MM-dd HH:mm`
)->a( n = `value` v = client->_bind( c_end )
)->tag( n = `Title` ns = `core`
)->a( n = `text` v = `Recurrence (optional)`
)->tag( `Label`
)->a( n = `text` v = `Repeat`
)->ele( `Select`
)->a( n = `selectedKey` v = client->_bind( c_rec_type )
)->a( n = `change` v = client->_event( `RECURRENCE_TYPE` )
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = ``
)->a( n = `text` v = `Does not repeat`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `Daily`
)->a( n = `text` v = `Daily`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `Weekly`
)->a( n = `text` v = `Weekly`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `Monthly`
)->a( n = `text` v = `Monthly`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `Yearly`
)->a( n = `text` v = `Yearly`
)->end(
)->tag( `Label`
)->a( n = `text` v = `Every`
)->a( n = `visible` v = |\{= ${ client->_bind( c_rec_type ) } !== '' \}|
)->ele( `HBox`
)->a( n = `alignItems` v = `Center`
)->a( n = `visible` v = |\{= ${ client->_bind( c_rec_type ) } !== '' \}|
)->tag( `Input`
)->a( n = `value` v = client->_bind( c_rec_pattern )
)->a( n = `type` v = `Number`
)->a( n = `width` v = `60px`
)->a( n = `placeholder` v = `1`
)->tag( `Text`
)->a( n = `text` v = |\{= ${ client->_bind( c_rec_type ) } === 'Daily' ? 'day(s)' : | &&
|${ client->_bind( c_rec_type ) } === 'Weekly' ? 'week(s)' : | &&
|${ client->_bind( c_rec_type ) } === 'Monthly' ? 'month(s)' : 'year(s)' \}|
)->a( n = `class` v = `sapUiSmallMarginBegin`
)->end(
)->tag( `Label`
)->a( n = `text` v = `On`
)->a( n = `visible` v = |\{= ${ client->_bind( c_rec_type ) } === 'Weekly' \}|
)->ele( `MultiComboBox`
)->a( n = `selectedKeys` v = client->_bind( c_rec_days )
)->a( n = `visible` v = |\{= ${ client->_bind( c_rec_type ) } === 'Weekly' \}|
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `0`
)->a( n = `text` v = `Sunday`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `1`
)->a( n = `text` v = `Monday`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `2`
)->a( n = `text` v = `Tuesday`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `3`
)->a( n = `text` v = `Wednesday`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `4`
)->a( n = `text` v = `Thursday`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `5`
)->a( n = `text` v = `Friday`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `6`
)->a( n = `text` v = `Saturday`
)->end(
)->tag( `Label`
)->a( n = `text` v = `Repeat on`
)->a( n = `visible` v = |\{= ${ client->_bind( c_rec_type ) } === 'Monthly' \|\| ${ client->_bind( c_rec_type ) } === 'Yearly' \}|
)->ele( `Select`
)->a( n = `selectedKey` v = client->_bind( c_rule_type )
)->a( n = `visible` v = |\{= ${ client->_bind( c_rec_type ) } === 'Monthly' \|\| ${ client->_bind( c_rec_type ) } === 'Yearly' \}|
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `DayOfMonth`
)->a( n = `text` v = `A specific day of the month`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `DayOfWeek`
)->a( n = `text` v = `A specific day of the week`
)->end(
)->tag( `Label`
)->a( n = `text` v = `On day`
)->a( n = `visible` v = |\{= (${ client->_bind( c_rec_type ) } === 'Monthly' \|\| ${ client->_bind( c_rec_type ) } === 'Yearly') && | &&
|${ client->_bind( c_rule_type ) } === 'DayOfMonth' \}|
)->tag( `Input`
)->a( n = `value` v = client->_bind( c_rule_dom )
)->a( n = `type` v = `Number`
)->a( n = `width` v = `80px`
)->a( n = `visible` v = |\{= (${ client->_bind( c_rec_type ) } === 'Monthly' \|\| ${ client->_bind( c_rec_type ) } === 'Yearly') && | &&
|${ client->_bind( c_rule_type ) } === 'DayOfMonth' \}|
)->a( n = `placeholder` v = `e.g. 15`
)->tag( `Label`
)->a( n = `text` v = `On the`
)->a( n = `visible` v = |\{= (${ client->_bind( c_rec_type ) } === 'Monthly' \|\| ${ client->_bind( c_rec_type ) } === 'Yearly') && | &&
|${ client->_bind( c_rule_type ) } === 'DayOfWeek' \}|
)->ele( `HBox`
)->a( n = `alignItems` v = `Center`
)->a( n = `visible` v = |\{= (${ client->_bind( c_rec_type ) } === 'Monthly' \|\| ${ client->_bind( c_rec_type ) } === 'Yearly') && | &&
|${ client->_bind( c_rule_type ) } === 'DayOfWeek' \}|
)->ele( `Select`
)->a( n = `selectedKey` v = client->_bind( c_rule_wom )
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `First`
)->a( n = `text` v = `First`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `Second`
)->a( n = `text` v = `Second`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `Third`
)->a( n = `text` v = `Third`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `Fourth`
)->a( n = `text` v = `Fourth`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `Last`
)->a( n = `text` v = `Last`
)->end(
)->ele( `Select`
)->a( n = `selectedKey` v = client->_bind( c_rule_dow )
)->a( n = `class` v = `sapUiSmallMarginBegin`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `0`
)->a( n = `text` v = `Sunday`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `1`
)->a( n = `text` v = `Monday`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `2`
)->a( n = `text` v = `Tuesday`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `3`
)->a( n = `text` v = `Wednesday`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `4`
)->a( n = `text` v = `Thursday`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `5`
)->a( n = `text` v = `Friday`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `6`
)->a( n = `text` v = `Saturday`
)->end(
)->end(
)->tag( `Label`
)->a( n = `text` v = `In`
)->a( n = `visible` v = |\{= ${ client->_bind( c_rec_type ) } === 'Yearly' \}|
)->ele( `Select`
)->a( n = `selectedKey` v = client->_bind( c_rule_month )
)->a( n = `visible` v = |\{= ${ client->_bind( c_rec_type ) } === 'Yearly' \}|
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `0`
)->a( n = `text` v = `January`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `1`
)->a( n = `text` v = `February`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `2`
)->a( n = `text` v = `March`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `3`
)->a( n = `text` v = `April`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `4`
)->a( n = `text` v = `May`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `5`
)->a( n = `text` v = `June`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `6`
)->a( n = `text` v = `July`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `7`
)->a( n = `text` v = `August`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `8`
)->a( n = `text` v = `September`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `9`
)->a( n = `text` v = `October`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `10`
)->a( n = `text` v = `November`
)->tag( n = `Item` ns = `core`
)->a( n = `key` v = `11`
)->a( n = `text` v = `December`
)->end(
)->tag( `Label`
)->a( n = `text` v = `Until`
)->a( n = `visible` v = |\{= ${ client->_bind( c_rec_type ) } !== '' \}|
)->tag( `DatePicker`
)->a( n = `visible` v = |\{= ${ client->_bind( c_rec_type ) } !== '' \}|
" the original binds this typed too (sap.ui.model.type.Date,
" pattern 'yyyy-MM-dd'); valueFormat carries the same contract
" without raising on the empty value this field seeds with.
" The ISO datetime shape, not the original's date-only one, so
" recurrenceenddate matches the port's own seeded rows
)->a( n = `valueFormat` v = `yyyy-MM-dd'T'HH:mm:ss`
)->a( n = `displayFormat` v = `yyyy-MM-dd`
)->a( n = `value` v = client->_bind( c_rec_end )
)->end(
)->end(
)->ele( `beginButton`
)->tag( `Button`
)->a( n = `text` v = `Create`
)->a( n = `type` v = `Emphasized`
)->a( n = `press` v = client->_event( `CREATE_SAVE` )
)->end(
)->ele( `endButton`
)->tag( `Button`
)->a( n = `text` v = `Cancel`
)->a( n = `press` v = client->_event( `CREATE_CANCEL` ) ).
client->popup_display( popup->stringify( ) ).
ENDMETHOD.
METHOD on_event.
CASE client->get_event( ).
WHEN `CREATE_APPOINTMENT`.
create_reset( ).
popup_create_display( ).
WHEN `RECURRENCE_TYPE`.
" onRecurrenceTypeChange clears the parts the picked recurrence does not use
IF c_rec_type <> `Weekly`.
CLEAR c_rec_days.
ENDIF.
IF c_rec_type <> `Monthly` AND c_rec_type <> `Yearly`.
c_rule_type = `DayOfMonth`.
c_rule_dom = `0`.
c_rule_wom = `First`.
c_rule_dow = `0`.
ENDIF.
IF c_rec_type <> `Yearly`.
c_rule_month = `0`.
ENDIF.
WHEN `CREATE_SAVE`.
" onCreateDialogSave pushes the dialog's model into the appointments.
" The new row carries the CONTROL's own default recurrence pattern:
" setRecurrencePattern raises "recurrencePattern must be >= 1", and the
" original keeps the default by leaving the property off a non-recurring
" appointment - a serialized ABAP structure cannot leave a field out, so
" the initial 0 would reach the setter and terminate the app
DATA(new_appointment) = VALUE ty_s_appointment( start_at = c_start
end_at = c_end
title = c_title
text = c_text
type = c_type
recurrencepattern = 1 ).
IF c_rec_type IS NOT INITIAL.
new_appointment-recurrencetype = c_rec_type.
" guarded on characters AND length: c_rec_pattern comes straight from a
" free-entry Input, so an unguarded CONV i can raise NO_NUMBER or
" OVERFLOW; an unusable entry falls back to the sample's default
new_appointment-recurrencepattern = COND i( WHEN c_rec_pattern CO `0123456789` AND c_rec_pattern IS NOT INITIAL
AND strlen( c_rec_pattern ) <= 9
THEN CONV i( c_rec_pattern )
ELSE 1 ).
new_appointment-recurrenceenddate = c_rec_end.
IF c_rec_type = `Weekly` AND c_rec_days IS NOT INITIAL.
new_appointment-t_recurrence_day = c_rec_days.
ENDIF.
IF c_rec_type = `Monthly` OR c_rec_type = `Yearly`.
new_appointment-ruletype = c_rule_type.
IF c_rule_type = `DayOfMonth`.
" same guard as recurrencepattern above - c_rule_dom is free entry too
new_appointment-ruledayofmonth = COND i( WHEN c_rule_dom CO `0123456789` AND c_rule_dom IS NOT INITIAL
AND strlen( c_rule_dom ) <= 9
THEN CONV i( c_rule_dom )
ELSE 0 ).
ELSE.
new_appointment-ruleweekofmonth = c_rule_wom.
new_appointment-ruledayofweek = CONV i( c_rule_dow ).
ENDIF.
ENDIF.
IF c_rec_type = `Yearly`.
new_appointment-rulemonth = CONV i( c_rule_month ).
ENDIF.
ENDIF.
INSERT new_appointment INTO TABLE t_appointments.
client->popup_destroy( ).
client->message_toast_display( |Appointment '{ c_title }' created.| ).
WHEN `CREATE_CANCEL`.
client->popup_destroy( ).
ENDCASE.
ENDMETHOD.
METHOD create_reset.
" onCreateAppointment reseeds the dialog model: the next full hour and the
" hour after it. A backend has no client clock, so the seed is the sample's
" own calendar day at the next full hour of the SERVER time (see sidecar)
DATA(now) = sy-timlo.
c_title = ``.
c_text = ``.
c_type = `Type01`.
c_start = |{ sy-datlo DATE = ISO }T{ now(2) }:00:00|.
c_end = |{ sy-datlo DATE = ISO }T{ CONV i( now(2) ) + 1 WIDTH = 2 ALIGN = RIGHT PAD = '0' }:00:00|.
c_rec_type = ``.
c_rec_pattern = `1`.
CLEAR c_rec_days.
c_rec_end = ``.
c_rule_type = `DayOfMonth`.
c_rule_dom = `0`.
c_rule_wom = `First`.
c_rule_dow = `0`.
c_rule_month = `0`.
ENDMETHOD.
METHOD model_init.
start_date = `2024-01-01T00:00:00`.
create_reset( ).
t_appointments = VALUE #(
( start_at = `2024-01-01T09:00:00` end_at = `2024-01-01T09:15:00` title = `Daily Standup (every day)` text = `Should appear every single day` type = `Type05` recurrencetype = `Daily` recurrencepattern = 1
recurrenceenddate = `2024-12-31T00:00:00` )
( start_at = `2024-01-01T16:00:00` end_at = `2024-01-01T16:30:00` title = `Log Review (every 2 days)` text = `Should appear every other day: Jan 1, 3, 5, 7...` type = `Type08` recurrencetype = `Daily` recurrencepattern = 2
recurrenceenddate = `2024-12-31T00:00:00` )
( start_at = `2024-01-01T10:00:00` end_at = `2024-01-01T11:00:00` title = `Team Meeting (every Mon)` text = `Should appear once per week on Monday` type = `Type01` recurrencetype = `Weekly` recurrencepattern = 1
recurrenceenddate = `2024-12-31T00:00:00` t_recurrence_day = VALUE #( ( 1 ) ) )
( start_at = `2024-01-03T14:00:00` end_at = `2024-01-03T15:30:00` title = `Code Review (every Wed+Fri)` text = `Should appear twice per week: Wednesday and Friday` type = `Type02` recurrencetype = `Weekly` recurrencepattern = 1
recurrenceenddate = `2024-12-31T00:00:00` t_recurrence_day = VALUE #( ( 3 ) ( 5 ) ) )
( start_at = `2024-01-02T11:00:00` end_at = `2024-01-02T11:30:00` title = `1-on-1 (every 2nd Tue)` text = `Should appear every other Tuesday: Jan 2, 16, 30...` type = `Type06` recurrencetype = `Weekly` recurrencepattern = 2
recurrenceenddate = `2024-12-31T00:00:00` t_recurrence_day = VALUE #( ( 2 ) ) )
( start_at = `2024-01-01T13:00:00` end_at = `2024-01-01T14:30:00` title = `Retro (1st of each month)` text = `Should appear on the 1st of every month: Jan 1, Feb 1...` type = `Type03` recurrencetype = `Monthly` recurrencepattern = 1
recurrenceenddate = `2026-12-31T00:00:00` )
( start_at = `2024-01-15T09:00:00` end_at = `2024-01-15T12:00:00` title = `Board Review (every 3 months)` text = `Should appear quarterly on 15th: Jan 15, Apr 15, Jul 15, Oct 15` type = `Type07` recurrencetype = `Monthly`
recurrencepattern = 3 recurrenceenddate = `2026-12-31T00:00:00` )
( start_at = `2024-01-15T00:00:00` end_at = `2024-01-15T23:59:00` title = `Company Kickoff (yearly Jan 15)` text = `Should appear once per year on January 15` type = `Type04` recurrencetype = `Yearly` recurrencepattern = 1
recurrenceenddate = `2026-12-31T00:00:00` )
( start_at = `2024-03-10T10:00:00` end_at = `2024-03-10T11:30:00` title = `Perf Review (yearly Mar 10)` text = `Should appear once per year on March 10` type = `Type09` recurrencetype = `Yearly` recurrencepattern = 1
recurrenceenddate = `2026-12-31T00:00:00` )
).
t_non_working = VALUE #(
( date_at = `2024-01-01T00:00:00` start_at = `00:00` end_at = `08:00` valueformat = `HH:mm` title = `Before Work Hours` recurrencetype = `Weekly` recurrencepattern = 1 recurrenceenddate = `2024-12-31T00:00:00`
t_recurrence_day = VALUE #( ( 1 ) ( 2 ) ( 3 ) ( 4 ) ( 5 ) ) )
( date_at = `2024-01-01T00:00:00` start_at = `12:00` end_at = `13:00` valueformat = `HH:mm` title = `Lunch Break` recurrencetype = `Weekly` recurrencepattern = 1 recurrenceenddate = `2024-12-31T00:00:00`
t_recurrence_day = VALUE #( ( 1 ) ( 2 ) ( 3 ) ( 4 ) ( 5 ) ) )
( date_at = `2024-01-01T00:00:00` start_at = `18:00` end_at = `23:59` valueformat = `HH:mm` title = `After Work Hours` recurrencetype = `Weekly` recurrencepattern = 1 recurrenceenddate = `2024-12-31T00:00:00`
t_recurrence_day = VALUE #( ( 1 ) ( 2 ) ( 3 ) ( 4 ) ( 5 ) ) )
( date_at = `2024-01-06T00:00:00` start_at = `00:00` end_at = `23:59` valueformat = `HH:mm` title = `Weekend - Saturday` recurrencetype = `Weekly` recurrencepattern = 1 recurrenceenddate = `2024-12-31T00:00:00`
t_recurrence_day = VALUE #( ( 6 ) ) )
( date_at = `2024-01-07T00:00:00` start_at = `00:00` end_at = `23:59` valueformat = `HH:mm` title = `Weekend - Sunday` recurrencetype = `Weekly` recurrencepattern = 1 recurrenceenddate = `2024-12-31T00:00:00`
t_recurrence_day = VALUE #( ( 0 ) ) )
( date_at = `2024-01-01T00:00:00` start_at = `02:00` end_at = `02:30` valueformat = `HH:mm` title = `Server Backup` recurrencetype = `Daily` recurrencepattern = 1 recurrenceenddate = `2024-12-31T00:00:00` )
( date_at = `2024-01-01T00:00:00` start_at = `06:00` end_at = `08:00` valueformat = `HH:mm` title = `Monthly Maintenance` recurrencetype = `Monthly` recurrencepattern = 1 recurrenceenddate = `2026-12-31T00:00:00` )
( date_at = `2024-01-15T00:00:00` start_at = `08:00` end_at = `12:00` valueformat = `HH:mm` title = `Monthly Inventory` recurrencetype = `Monthly` recurrencepattern = 1 recurrenceenddate = `2026-12-31T00:00:00` )
( date_at = `2024-01-01T00:00:00` start_at = `00:00` end_at = `23:59` valueformat = `HH:mm` title = `New Year's Day` recurrencetype = `Yearly` recurrencepattern = 1 recurrenceenddate = `2026-12-31T00:00:00` )
( date_at = `2024-07-04T00:00:00` start_at = `00:00` end_at = `23:59` valueformat = `HH:mm` title = `Independence Day` recurrencetype = `Yearly` recurrencepattern = 1 recurrenceenddate = `2026-12-31T00:00:00` )
( date_at = `2024-12-25T00:00:00` start_at = `00:00` end_at = `23:59` valueformat = `HH:mm` title = `Christmas Day` recurrencetype = `Yearly` recurrencepattern = 1 recurrenceenddate = `2026-12-31T00:00:00` )
).
ENDMETHOD.
ENDCLASS.
More in sap.m
- Single Planning Calendar — This sample demonstrates most of the features available for the SinglePlanningCalendar co…
- Single Planning Calendar - Week Numbering — This sample demonstrates how the SinglePlanningCalendar control can be used width differe…
- Single Planning Calendar with Snapping Header and option to change the first day of week — SinglePlanningCalendar showing the modes for snapping the header part of the calendar.
- Single Planning Calendar with Custom Views — SinglePlanningCalendar showing the provided predefined views and custom views.
- Single Planning Calendar with Legend and defined working hours — SinglePlanningCalendar and PlanningCalendarLegend controls used as main and side parts of…
- Single Planning Calendar with Zoom In and Zoom Out behavior — SinglePlanningCalendar with enabled Zoom In and Zoom Out functionality.
- 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…
- Dialog with Custom Footer — Dialog with custom footer and support for message popover.
- Message View inside Popover — A sample with Message View inside a Popover.
On this page