Erscheinungsmonat | APEX-Version | Datenbankversion | Cloud oder on Premise |
Februar 2016 | 5.0 | ab 11.2 | on Premise und Cloud |
Eine Kalenderansicht gehört zum Standardumfang vieler Anwendungen - dementsprechend stellt APEX seit der ersten Version einen Kalender bereit. Mit APEX 5.0 wurde dieser allerdings gründlich modernisiert: APEX setzt nun auf dem populären jQuery-Plugin FullCalendar auf und stellt dem Entwickler eine Komponente bereit, die es erlaubt, mit wenig Aufwand eine Kalenderansicht mit modernem Look & Feel bereitzustellen.
Im ersten Teil des Tipp wurde der Kalender vorgestellt und es wurde gezeigt, wie man mit Hilfe von SQL-Funktionen wiederkehrende Ereignisse darstellen kann. In diesem Teil, der direkt auf dem ersten Teil aufbaut, zeigen wir, wie Sie die Kalenderansicht noch individueller gestalten oder die jQuery FullCalendar API direkt nutzen können.
Icons zu Kalendereinträgen hinzufügen
APEX enthält ja von Haus aus die Icon Bibliothek Font Awesome, da liegt es nahe, die Kalenderansicht mit Font Awesome Icons anzureichern.
Abbildung 1: Kalenderansicht aus dem ersten Teil - ohne "wiederkehrende" Ereignisse
Die SQL-Query, die dem Kalender zugrundeliegt, liefert bereits eine Spalte namens CSS_CLASS zurück. Im ersten Teil des Tipps wurde hiermit allein die Farbe des Eintrags gesteuert (apex-cal-blue, apex-cal-red, etc.) Nun liegt es nahe, hier einfach entsprechende Font-Awesome-Klassen hinzuzufügen. Ändern Sie die SQL-Abfrage des Kalenders also wie folgt um (der Teil für die wiederkehrenden Ereignisse wurde der Einfachheit halber weggelassen).
select id, title, descr, start_date, end_date, case when event_type='WEB' then 'fa fa-desktop apex-cal-green' when event_type='USERGROUP' then 'fa fa-users apex-cal-red' when event_type='INTERN' then 'fa fa-lock apex-cal-blue' end as css_class from tab_events
Nun sieht der Kalender in etwa wie folgt aus.
Abbildung 2: Kalenderansicht mit zusätzlichen Font Awesome Symbolen
Allerdings entspricht das nicht ganz dem gewünschten Ergebnis - zwar sind die gewünschten Symbole vorhanden, allerdings stehen diese über dem Eintrag für das Ereignis, und außerdem gibt es einen Einfluß auf die Schriftart: die hat sich nun geändert. Beides soll nicht sein - die Schriftart soll bleiben, wie sie ist; außerdem soll das Icon entweder links oder rechts des Eintrags stehen.
Die vorgegebenen Font Awesome-Klassen reichen hierfür nicht aus - man muss sich eigene erstellen. Ändern Sie also die SQL-Abfrage nochmals wie folgt um, so dass anstelle der Font Awesome-Klassen fa-users, fa-desktop und fa-lock die Klassennamen myicon-users, myicon-desktop und myicon-lock verwendet werden.
select id, title, descr, start_date, end_date, case when event_type='WEB' then 'myicon-right myicon-desktop apex-cal-green' when event_type='USERGROUP' then 'myicon-right myicon-users apex-cal-red' when event_type='INTERN' then 'myicon-right myicon-lock apex-cal-blue' end as css_class from tab_events
Diese Klassen müssen nun definiert werden. Navigieren Sie zu den Seitenattributen, dort zum Bereich CSS und zum Parameter Inline. Fügen Sie dort den folgenden CSS-Code hinzu.
.myicon-left .fc-content .fc-title:before { font-family: FontAwesome; margin-right: 5px; float: left; } .myicon-right .fc-content .fc-title:before { font-family: FontAwesome; margin-left: 5px; float: right; } .myicon-desktop .fc-content .fc-title:before { content: '\f108'; } .myicon-users .fc-content .fc-title:before { content: '\f0c0'; } .myicon-lock .fc-content .fc-title:before { content: '\f023'; }
Zunächst erfolgen die Definitionen der Klassen myicon-left und myicon-right, die festlegen, ob das Icon links oder rechts anzeigt werden soll. Die darauf folgenden drei CSS-Klassen legen mit dem Attribut content fest, welches Icon konkret verwendet werden soll. Die Codepunkte lassen sich am einfachsten aus dem Font Awesome Cheatsheet entnehmen, dort stehen sie bei jedem Icon.
Abbildung 3: Codepunkte der Font Awesome-Icons im Font Awesome Cheatsheet
Wenn Sie die Kalenderansicht nun nochmals starten, so erscheinen die Icons genau da, wo sie sollen. Der einzige Nachteil der Methode ist, dass Sie für jedes Icon, dass Sie verwenden möchten, eine neue CSS-Klasse brauchen - allerdings braucht es typischerweise nur eine überschaubare Anzahl von Symbolen.
Abbildung 4: Kalenderansicht mit Font Awesome Symbolen - nun an der richtigen Stelle
jQuery FullCalendar API direkt nutzen
Schaut man sich die Dokumentation zu jQuery Fullcalendar genauer an, so sieht man, dass es jede Menge Möglichkeiten gibt, die Kalenderansicht noch individueller zu gestalten; es sind aber bei weitem nicht so viele APEX-Attribute vorhanden. Möchte man den vollen Funktionsumfang von jQuery Fullcalendar nutzen, so kann man die API auch direkt verwenden.
Sie sollten den im folgenden vorgestellten, manuellen, Ansatz zum Einbinden eines jQuery FullCalendar nur dann verwenden, wenn Sie Ihre Anforderungen mit dem Standard-APEX-Kalender nicht umsetzen können. Aus Sicht von APEX wird kein Kalender erstellt, sondern eine HTML-Region, ein AJAX-Callback und etwas Javascript Code.
Als Beispiel soll uns ein Wochenplan dienen; also eine Ansicht, die Ereignisse in der Wochenansicht anzeigt, aber kein konkretes Datum verwendet. Lediglich Wochentage und Uhrzeiten werden sichtbar sein. Das Besondere ist, dass diese Darstellung keinen Bezug zu einem konkreten Datum haben und immer gültig sein soll. Das sieht der APEX-Kalender nicht vor.
Abbildung 5: Ziel - Ein Wochenplan als jQuery Fullcalendar
Zunächst braucht es wiederum eine Tabelle, welche die Daten hält. Diese sieht so ähnlich aus, wie unsere erste Tabelle, anstelle der konkreten Beginn und Ende-Zeiträume braucht es hier aber etwas andere Spalten.
create table tab_weekplan( id number(10) generated always as identity primary key, title varchar2(200) not null, weekday number(1), start_time varchar2(5), end_time varchar2(5), event_type varchar2(20), constraint ck_weekday check (weekday between 1 and 7), constraint ck_starttime check (regexp_instr(start_time, '^\d\d\:\d\d$') = 1), constraint ck_endtime check (regexp_instr(end_time, '^\d\d\:\d\d$') = 1) ) / insert into tab_weekplan (title, weekday, start_time, end_time, event_type) values ('Montags-Telco', 1, '10:00', '11:00', 'TELCO') / insert into tab_weekplan (title, weekday, start_time, end_time, event_type) values ('Gruppenmeeting', 5, '14:00', '14:00', 'MEETING') / insert into tab_weekplan (title, weekday, start_time, end_time, event_type) values ('Redaktionskonferenz', 3, '09:00', '12:00', 'MEETING') / insert into tab_weekplan (title, weekday, start_time, end_time, event_type) values ('Project Scrum', 4, '09:00', '09:30', 'MEETING') /
Die Ereignisse werden nun durch die Spalten WEEKDAY, START_TIME und END_TIME festgelegt. Da es hierfür keine passenden Datentypen gibt, helfen wir uns mit NUMBER und VARCHAR2-Spalten, die durch Check-Constraints entsprechend abgesichert werden. Beim Wochentag soll die 1 für den Montag und die 7 für den Sonntag stehen. Als nächstes geht es daran, die Kalenderansicht zu erstellen. Erzeugen Sie dazu eine APEX-Seite mit einer leeren Region vom Typ Static Content. Navigieren Sie für diese zum Bereich Advanced und tragen Sie WOCHENPLAN als Static ID ein.
Abbildung 6: Static ID der Region auf "WOCHENPLAN" setzen
Als nächstes brauchen Sie einen AJAX-Callback, welcher die Kalenderdaten im JSON-Format zurückliefert. Klicken Sie dazu im Page Designer links auf den Reiter für die Prozesse, klicken die die rechte Maustaste bei AJAX Callbacks und erzeugen Sie so einen neuen Prozess.
Abbildung 7: Neuen AJAX Callback erzeugen
Nennen Sie den Prozess holeWochenplan und hinterlegen Sie den folgenden PL/SQL-Code. Speichern Sie den Prozess danach ab.
begin apex_json.open_array; for i in ( select id, title, to_date('2016-01-10 '||start_time, 'YYYY-MM-DD HH24:MI') + weekday as start_time, to_date('2016-01-10 '||end_time, 'YYYY-MM-DD HH24:MI') + weekday as end_time, case when event_type='MEETING' then 'apex-cal-green' when event_type='TELCO' then 'apex-cal-red' end as css_class from tab_weekplan ) loop apex_json.open_object; apex_json.write('id', i.id); apex_json.write('title', i.title); apex_json.write('start', to_char(i.start_time, 'YYYY-MM-DD"T"HH24:MI:SS')); apex_json.write('end', to_char(i.end_time, 'YYYY-MM-DD"T"HH24:MI:SS')); apex_json.write('className', i.css_class); apex_json.close_object; end loop; apex_json.close_array; end;
Der PL/SQL liest die Daten aus der Tabelle TAB_WEEKPLAN aus und generiert daraus mit Hilfe des PL/SQL Pakets APEX_JSON eine JSON-Ausgabe. Interessant ist der Umgang mit den Zeit und Wochentagsangaben: Ausgehend vom 10. Januar 2016 (welcher ein Sonntag ist), werden, anhand der Spalten WEEKDAY, START_TIME und END_TIME, konkrete Ereignisse für die konkrete Woche vom 11. Januar bis zum 17. Januar 2016 generiert. Alle in der Tabelle stehenden Ereignisse werden auf diese Woche abgebildet. Die Kalenderansicht wird genau diese Woche zeigen und alle Datumsangaben und Navigationselemente werden entfernt, so dass die Woche nicht verlassen werden kann. Folglich entsteht ein immer gültiger Wochenplan.
Sie können den neuen AJAX-Callback testen, indem Sie ihn per URL explizit aufrufen:
http://{server}:{port}/apex/f?p={application-id}:{page-id}:{session}:APPLICATION_PROCESS=holeWochenplan
Abbildung 8: AJAX Callback testen
Nun navigieren Sie zu den Seitenattributen und hinterlegen Sie im Bereich Javascript bei Function/Global Variable declaration den folgenden Javascript Code. Der erzeugt mit Hilfe der jQuery FullCalendar API eine neue Kalenderansicht, bei der einige Dinge anders eingestellt sind, als beim APEX-Kalender.
function doCalendar(pRegionStaticId, pAjaxCallbackName, pTitle) { apex.jQuery("#"+pRegionStaticId).fullCalendar({ header: {left: '', center: 'title', right: ''}, columnFormat: {month: '', week: 'dddd', day: ''}, minTime: '08:00:00', maxTime: '18:00:00', timeFormat: "H:mm", axisFormat: 'H:mm', allDaySlot: false, weekends: true, firstDay: 1, dayNames: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"], contentHeight: 550, slotEventOverlap: true, defaultView: 'agendaWeek', defaultDate: moment('2016-01-11'), titleFormat: '[' + pTitle + ']', events: function(start, end, timezone, callback) { apex.server.process( pAjaxCallbackName, { // Page Items und apex_application.g_x## Variablen hier hinzufügen }, { success: function(jsondata) { callback((jsondata)); } } ); } }); }
Im Bereich Execute when Page loads rufen Sie Ihre Javascript Funktion auf - hinterlegen Sie dort:
doCalendar("WOCHENPLAN", "holeWochenplan", "Wochenplan")
Da Sie nicht die APEX-Kalenderregion verwenden, sondern aus APEX Sicht "nur" mit einer HTML-Region und etwas Javascript Code arbeiten, wird APEX die Javascript-Bibliotheken und CSS-Dateien des jQuery FullCalendar nicht laden. Also müssen Sie diese Ihrer Anwendung hinzufügen. Um bei künftigen APEX-Upgrades stabil zu bleiben, empfiehlt es sich in diesem Fall, jQuery FullCalendar selbst herunterzuladen.
Abbildung 10: jQuery FullCalendar herunterladen.
Laden Sie das ZIP-Archiv dann als Static Application File in den APEX-Workspace hochzuladen. Achten Sie darauf, dass APEX das ZIP-Archiv anschließend auspackt.
Abbildung 11: jQuery FullCalendar in den APEX-Workspace hochladen
Navigieren Sie dann wieder zu Ihrer APEX-Seite und nehmen Sie folgende Einstellungen in den Seitenattributen vor.
#APP_IMAGES#fullcalendar-2.6.0/lib/moment.min.js #APP_IMAGES#fullcalendar-2.6.0/fullcalendar.js
#APP_IMAGES#fullcalendar-2.6.0/fullcalendar.css
Speichern Sie alles ab und starten Sie die Seite neu. Nun ist alles fertig und Ihr APEX-Wochenplan sollte wie gewünscht aussehen.
Abbildung 9: Wochenplan auf Basis einer Tabelle und jQuery FullCalendar
So haben Sie "Ihren eigenen" jQuery FullCalendar in Ihre APEX-Anwendung integriert. Sie sind nun natürlich auch komplett selbst verantwortlich. So wird die jQuery FullCalendar-Version für diese Anwendung natürlich nicht mit neuen APEX-Releases automatisch aktualisiert; das müssen Sie durch erneutes Hochladen selbst tun. Im Gegenzug bekommen Sie viele Möglichkeiten, das Aussehen des Kalenders selbst zu beeinflussen.
Fazit
Kalender lassen sich auf vielfältige Art und Weise in APEX-Anwendungen integrieren. Eine SQL-Abfrage als Datenquelle reicht bereits aus, um Ereignisse in modernem Look & Feel im Browser darzustellen. Nutzt man die Möglichkeiten von SQL geschickt aus, so können auch Ereignisse dargestellt werden, die sich nicht 1:1 in einer Tabelle wiederfinden. Anwenderfreundliche Funktionen wie Drag & Drop werden ebenso unterstützt wie verschiedene Kalenderansichten.
Wie immer ist es mit APEX-Komponenten recht einfach, über den out-of-the-box gelieferten Standard hinauszugehen. So können Kalendereinträge durch geschicktes Setzen von CSS-Klassen mit Icons versehen werden. Wer eine völlig individuelle Kalendersicht braucht, nutzt die Javascript-API von jQuery FullCalendar direkt.