Creare un componente calendario in Power Apps
In Power Apps non esiste nativamente un controllo calendario, ma può comunque essere realizzato tramite un componente.vediamo come.
A questo punto si possono impostare le proprietà dei controlli per:
Entrando nel dettaglio, le proprietà dei controlli andranno impostate nel modo seguente:
In particolare la gallery glryDays dovrà avere la proprietà Items impostata con una collection fissa che copra il numero di giorni visualizzabili: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41].
Sia glryHeader che glryDays dovranno avere la proprietà WrapCount uguale a 7 per fare in modo che le colonne si ripetano orizzontalmente.
La proprietà Text della label lblDay dovrà visualizzare il giorno corretto: Day(DateAdd(_firstDate, ThisItem.Value, Days)).
Il background del rettangolo rectDay, proprietà Fill, evidenzierà se il giorno fa parte o meno del mese selezionato:If(_month = Month(DateAdd(_firstDate, ThisItem.Value, Days)) ,CompSgartCalendar.DayFill, RGBA(0,0,0,0))
Realizzare questo controllo è un buon esercizio didattico che aiuta a prendere familiarità con il mondo Power Apps e i componenti.
Component
Per prima cosa creiamo un nuovo componenteVanno aggiunte due gallery blank vertical, una per l'header delle colonne e uno per i giorni del mese:Il nuovo componente avrà questa struttura:- CompSgartCalendar
- lblCopyright
- glryHeader
- lblHeader
- rectHeader
- glryDays
- lblDay
- icnEvent
- icnToday
- rectDay
Custom properties
Perchè funzioni, vanno aggiunte delle custom properties al componente:#class=table-striped Display name;Name;Property Type;Data Type;Rise OnReset;DefaultValue Current date;CurrentDate;Input;Date andTime;true;Today() Current day color;CurrentDayColor;Input;Color;false;RGBA(128, 0, 0, 1) Event dates;EventDates;Input;Table;false;[Today(), Today()+1] Event color;eventColor;Input;Color;false;RGBA(255, 0, 0, 1) Header labels;HeaderLabels;Input;Table;false;["Lun", "Mar", "Mer", "Gio", "Ven","Sab", "Dom"] Header fill;HeaderFill;Input;Color;false;RGBA(255, 119, 40, 1) Header color;HeaderColor;Input;Color;false;RGBA(250, 250,250, 1) Day fill;DayFill;Input;Color;false;RGBA(246, 239, 221, 1) Day color;DayColor;Input;Color;false;RGBA(0, 0, 0, 1) Selectedcolor;SelectedColor;Input;Color;false;RGBA(255, 119, 40, .5) Selected date;SelectedDate;Output;Date and time;false;_selectedDatei valori di default delle proprietà possono essere impostate andando nella scheda AdvancedLe proprietà permettono di impostare la data del mese da visualizzare, i colori dei vari elementi, oltre a poter ottenere la proprietà di uscita (SelectedDate).
Set componente
Il passo successivo è fare alcune inizializzazioni nell'evento OnResetPower Apps
/* giorno corrente */
Set(_currentDate, Today());
If(IsBlank(CompSgartCalendar.CurrentDate) = false, Set(_currentDate, CompSgartCalendar.CurrentDate));
/* data scelta dall'utente di output */
Set(_selectedDate, _currentDate);
/* anno, mese, giorno corrente */
Set(_year, Year(_currentDate));
Set(_month, Month(_currentDate));
Set(_day, Day(_currentDate));
/* primo giorno del mese */
Set(_date1, DateAdd(_currentDate, -_day + 1, Days));
/* determino il gioro della sittimana */
Set(_dayOffset, Weekday(_date1, StartOfWeek.Monday)-1);
/* primo giorno visualizzato sul calenario */
Set(_firstDate, DateAdd(_date1, -_dayOffset,Days));
/* calcolo l'ultimo indice da visualizzare */
Set(_lastDay, Day(DateAdd(DateAdd(_date1, 1, Months), -1, Days)));
Set(_lastIndex, If(_dayOffset + _lastDay > 34, 41, 34));
- rendere il controllo responsive
- visualizzare il giorno corrente (Today)
- visualizzare un segno di spunta se la data è una di quelle passate nella proprietà EventDates
- evidenziare il giorno selezionato tramite click (valore che verrà riportato nella property di output SelectedDate)
Entrando nel dettaglio, le proprietà dei controlli andranno impostate nel modo seguente:
Power Apps
/* glryHeaders */
glryHeaders.BorderThickness = 0
glryHeaders.Fill = RGBA(0, 0, 0, 0)
glryHeaders.Height = Parent.Height / 7
glryHeaders.Items = CompSgartCalendar.HeaderLabels
glryHeaders.ShowScrollbar = false
glryHeaders.TemplatePadding = 2
glryHeaders.TemplateSize = Self.Height - Self.TemplatePadding * 2
glryHeaders.Width = Parent.Width
glryHeaders.WrapCount = 7
glryHeaders.X = 0
glryHeaders.Y = 0
/* glryHeaders lblHeader */
lblHeader.BorderThickness = 0
lblHeader.Color = CompSgartCalendar.HeaderColor
lblHeader.Fill = RGBA(0, 0, 0, 0)
lblHeader.FontWeight = Normal
lblHeader.Height = Parent.TemplateHeight
lblHeader.PaddingBottom = 0
lblHeader.PaddingLeft = 0
lblHeader.PaddingRight = 0
lblHeader.PaddingTop = 0
lblHeader.Text = ThisItem.Value
lblHeader.Width = Parent.TemplateWidth
lblHeader.X = 0
lblHeader.Y = 0
/* glryHeaders rectHeader */
rectHeader.BorderThickness = 0
rectHeader.Fill = CompSgartCalendar.HeaderFill
rectHeader.Height = Parent.TemplateHeight
rectHeader.Width = Parent.TemplateWidth
rectHeader.X = 0
rectHeader.Y = 0
/* glryDays */
glryDays.BorderThickness = 0
glryDays.Fill = RGBA(0, 0, 0, 0)
glryDays.Height =Parent.Height - glryHeaders.Height
glryDays.Items = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41]
glryDays.OnSelect = Set(_selectedDate, DateAdd(_firstDate, ThisItem.Value, Days))
glryDays.ShowScrollbar = false
glryDays.TemplatePadding = 2
glryDays.TemplateSize = Parent.Height / 7 - Self.TemplatePadding -1
glryDays.Width = Parent.Width
glryDays.WrapCount = 7
glryDays.X = 0
glryDays.Y = glryHeaders.Height
/* glryDays lblDay */
lblDay.BorderThickness = 0
lblDay.Color = If(IsNumeric(ThisItem.Value), CompSgartCalendar.DayColor, CompSgartCalendar.HeaderColor)
lblDay.Fill = If(DateAdd(_firstDate, ThisItem.Value, Days) = _selectedDate, CompSgartCalendar.SelectedColor, RGBA(0,0,0,0))
lblDay.FontWeight = Normal
lblDay.Height = Parent.TemplateHeight
lblDay.OnSelect = Select(Parent)
lblDay.PaddingBottom = 0
lblDay.PaddingLeft = 0
lblDay.PaddingRight = 0
lblDay.PaddingTop = 0
lblDay.Size = 21
lblDay.Text = Day(DateAdd(_firstDate, ThisItem.Value, Days))
lblDay.Visible =ThisItem.Value <= _lastIndex
lblDay.Width = Parent.TemplateWidth
lblDay.X = 0
lblDay.Y = 0
/* glryDays rectDay */
rectDay.BorderThickness = 0
rectDay.Fill = If(_month = Month(DateAdd(_firstDate, ThisItem.Value, Days)) ,CompSgartCalendar.DayFill, RGBA(0,0,0,0))
rectDay.Height = Parent.TemplateHeight
rectDay.Width = Parent.TemplateWidth
rectDay.X = 0
rectDay.Y = 0
/* glryDays icnEvent */
icnEvent.BorderThickness = 0
icnEvent.Color = CompSgartCalendar.EventColor
icnEvent.Fill = RGBA(0, 0, 0, 0)
icnEvent.Height = 20
icnEvent.Icon = Check
icnEvent.OnSelect = Select(Parent)
icnEvent.PaddingBottom = 0
icnEvent.PaddingLeft = 0
icnEvent.PaddingRight = 0
icnEvent.PaddingTop = 0
icnEvent.Visible = lblDay.Visible && IsBlank(LookUp(CompSgartCalendar.EventDates, ThisRecord.Value = DateAdd(_firstDate, ThisItem.Value, Days)).Value)=false
icnEvent.Width = 20
icnEvent.X = Parent.TemplateWidth - Self.Width - 5
icnEvent.Y = Parent.TemplateHeight - Self.Height - 5
/* glryDays icnToday (Right triangle) */
icnToday.BorderThickness = 0
icnToday.Fill = CompSgartCalendar.CurrentDayColor
icnToday.Height = 25
icnToday.OnSelect = Select(Parent)
icnToday.PaddingBottom = 0
icnToday.PaddingLeft = 0
icnToday.PaddingRight = 0
icnToday.PaddingTop = 0
icnToday.Visible = lblDay.Visible && DateAdd(_firstDate, ThisItem.Value, Days) = Today()
icnToday.Width = 25
icnToday.X = 0
icnToday.Y = Parent.TemplateHeight - Self.Height
/* lblCopyright */
lblDay.BorderThickness = 0
lblDay.Color = RGBA(127, 0, 0, .6)
lblDay.Fill = RGBA(0, 0, 0, 0)
lblDay.FontWeight = FontWeight.Bold
lblDay.Height = 40
lblDay.Size = 16
lblDay.Text = "sgart.it"
lblDay.Width = 150
lblDay.X = Parent.Width - Self.Width
lblDay.Y = Parent.Height - Self.Height
Sia glryHeader che glryDays dovranno avere la proprietà WrapCount uguale a 7 per fare in modo che le colonne si ripetano orizzontalmente.
La proprietà Text della label lblDay dovrà visualizzare il giorno corretto: Day(DateAdd(_firstDate, ThisItem.Value, Days)).
Il background del rettangolo rectDay, proprietà Fill, evidenzierà se il giorno fa parte o meno del mese selezionato:If(_month = Month(DateAdd(_firstDate, ThisItem.Value, Days)) ,CompSgartCalendar.DayFill, RGBA(0,0,0,0))
Screen
Una volta realizzato il componente può essere aggiunto alla pagina (screen):Nell'esempio i controlli hanno questa struttura:- ScrnCalendar
- icnright
- icnLeft
- lblMontYear
- lblTitleEvents
- lblSelected
- lblTitleSelected
- DatePicker1
- CompSgartCalendar_1 (il componente appena realizzato)
- glryDates
- lblDate
- lblDay
- icnEvent
- icnToday
- rectDay
Power Apps
/* App */
App.OnStart = ClearCollect(TableDates, [Today(), Date(2020,11,4), Date(2020,11,24), Date(2020,12,25), Date(2020,12,26)]); Set(_currentDate, Today());
/* DatePicker1 */
DatePicker1 .DefaultDate = _currentDate
/* CompSgartCalendar_1 */
CompSgartCalendar_1.CurrentDate = DatePicker1.SelectedDate
CompSgartCalendar_1.CurrentDayColor = RGBA(128, 0, 0, 1)
CompSgartCalendar_1.DayColor = RGBA(0, 0, 0, 1)
CompSgartCalendar_1.DayFill = RGBA(246, 239, 221, 1)
CompSgartCalendar_1.EventColor = RGBA(255, 0, 0, 1)
CompSgartCalendar_1.EventDates= TableDates
CompSgartCalendar_1.Fill = RGBA(253, 222, 207, .1)
CompSgartCalendar_1.HeaderColor = RGBA(250, 250,250, 1)
CompSgartCalendar_1.HeaderFill = RGBA(255, 119, 40, 1)
CompSgartCalendar_1.HeaderLabels = ["Lun", "Mar", "Mer", "Gio", "Ven","Sab", "Dom"]
CompSgartCalendar_1.SelectedColor = RGBA(255, 119, 40, .5)
/* lblSelected - visualizzo il parametro di output */
lblSelected .Text = Text(CompSgartCalendar_1.SelectedDate, DateTimeFormat.ShortDate, "it-IT")
/* icnRight - mese successivo */
icnRight.OnSelect = Set(_currentDate, DateAdd(DatePicker1.SelectedDate, 1,Months))
/* icnRight - mese precedente */
icnRight.OnSelect = Set(_currentDate, DateAdd(DatePicker1.SelectedDate, -1,Months))
/* glryDates */
glryDates.Items = SortByColumns(TableDates, "Value")
lblDate.Text = ThisItem.Value
La collection TableDates contiene le date degli eventi da visualizzare sul calendario. La label lblSelected visualizza il parametro di output del calendario SelectedDate.
Realizzare questo controllo è un buon esercizio didattico che aiuta a prendere familiarità con il mondo Power Apps e i componenti.