Logo Oracle Deutschland   Application Express Community
Dynamic Actions und eigenes JavaScript - Hand in Hand

Erscheinungsmonat APEX-Version Datenbankversion
Februar 2014 ab 4.0 ab 10.2

Dank der Dynamic Actions , die es bekanntlich seit APEX 4.0 gibt, ist die Nutzung der AJAX-Technologie in APEX sehr viel einfacher geworden - einfache Fälle wie das Auffrischen eines Berichts - oder das Setzen von Formularelementen ohne erneutes Laden der APEX-Seite, können komplett deklarativ eingerichtet werden; man programmiert keine einzige Zeile JavaScript mehr. Und es ist auch ganz generell empfehlenswert, den Dynamic Actions den Vorzug vor eigenem JavaScript Code zu geben - denn die Vorteile liegen auf der Hand ...

  • Die AJAX-Funktionalität einer APEX-Anwendung kann anhand des APEX-Dictionary nachvollzogen werden - alle Informationen über Dynamic Actions stehen in den Views APEX_APPLICATION_PAGE_DA und APEX_APPLICATION_PAGE_DA_ACTS bereit.
  • Eine Dynamic Action kann von einer ggfs. optimierten Umsetzung in einem künftigen Release profitieren - eigener JavaScript-Code wird immer so bleiben, wie er ist.

In der Praxis bleiben dann dennoch Fälle übrig, in denen man JavaScript manuell implementieren möchte oder muss. Ein Beispiel ist eine JavaScript-Aktion, die man per Klick auf eine Zeile in einem Bericht (interaktiv oder klassisch) auslösen möchte. Man kann keine dynamische Aktion "auf eine Berichtszeile" legen - man kann lediglich einen Spalten-Link erstellen, in dem man eine JavaScript-Funktion aufruft. Das ist aber nicht mehr deklarativ. Der heutige Tipp zeigt, wo und wie man Dynamic Actions auch für diese Fälle noch einsetzen kann.

Als Beispiel wollen wir eine "Kopierfunktion" für eine Tabellenzeile in einem APEX-Bericht implementieren - eine Berichtsspalte soll als Link aufbereitet werden; bei Klick darauf soll die Zeile kopiert werden (Abbildung 1).

Das Ziel: Kopierfunktion in einem APEX-Bericht - mit AJAX
Abbildung 1: Das Ziel: Kopierfunktion in einem APEX-Bericht - mit AJAX

Zunächst braucht es die Tabelle mit wenigstens einer Zeile.

create table tab_aufgaben(
  id            number(10) primary key,
  aufgabe       varchar2(200) not null,
  beschreibung  varchar2(4000) not null,
  bis_datum     date  not null,
  erstellt_am   date not null,
  prio          number not null
)
/

create sequence seq_aufgabe start with 1 increment by 1
/

create or replace trigger tr_pk_tab_aufgaben
before insert on tab_aufgaben
for each row
begin
  :new.id := seq_aufgabe.nextval;
  :new.erstellt_am := sysdate;
end;
/
sho err
      
insert into tab_aufgaben (
  aufgabe, beschreibung, bis_datum, prio
) values (
  'APEX Beispiel erstellen', 'APEX Beispiel für das Entwicklermeeting', DATE'2014-04-01', 1
)
/ 

Erzeugen Sie dann eine APEX-Anwendung mit einem Bericht auf diese Tabelle - ob Sie einen klassischen oder interaktiven Bericht nehmen, bleibt Ihnen überlassen.

Interaktiver Bericht für Tabelle "TAB_AUFGABEN"
Abbildung 2: Interaktiver Bericht für Tabelle "TAB_AUFGABEN"

Danach wird der PL/SQL-Code zum Kopieren der Tabellenzeile erstellt. Navigieren Sie zu den Gemeinsamen Komponenten und dort zu den Anwendungsprozessen. Erstellen Sie einen neuen Prozess mit dem Namen AufgabeKopieren. Er soll Bedarfsgesteuert (on Demand) ausgeführt werden. Hinterlegen Sie folgenden PL/SQL-Code.

declare
  -- im Parameter "x01" wird die ID der zu kopierenden Zeile übergeben
  l_aufg_id number := to_number(apex_application.g_x01);
begin
  insert into tab_aufgaben (
    aufgabe, beschreibung, bis_datum, prio
  ) (
   select aufgabe||' (Kopie)', beschreibung, bis_datum, prio 
   from tab_aufgaben 
   where id = l_aufg_id
  );

  htp.p('{"success": true}');
  -- Exception Handling fehlt noch ...
end;

Nun geht es an die JavaScript-Funktion, die diesen Anwendungsprozess via AJAX ausführt. Sie wird später bei Klick auf einen Link im Bericht ausgeführt. Navigieren Sie zu den Attributen der Anwendungsseite dort zum Bereich JavaScript - Function and Global Variable Declaration und hinterlegen Sie diesen Code.

function kopiereAufgabe(pAufgId) {
  apex.server.process ( 
    "AufgabeKopieren",
    {
      x01: pAufgId
    },
    {
      success: function (pData) {
        apex.event.trigger(document, "aufgabe_kopiert");
      },
    }
  );
}

Die hier verwendete JavaScript-Funktion apex.server.process ist weit mächtiger als das früher verwendete htmldb_Get - es ist zu empfehlen, künftig nur noch diese Funktion für AJAX-Requests zu nutzen. Achten Sie auf den Bereich success. Hier wird JavaScript-Code hinterlegt, der nach erfolgreicher Ausführung des AJAX-Requests gestartet werden soll. In diesem Fall wird einfach nur mit apex.event.trigger ein Ereignis (Event) ausgelöst. Das Event wird auf des DOM-Objekt document gelegt und trägt einen frei wählbaren Namen - für dieses Beispiel nehmen wir aufgabe_kopiert.

Nun wird es interessant. Wir erzeugen nun eine dynamische Aktion, mit der wir auf das ausgelöste Event reagieren werden. Vergeben Sie zunächst einen Namen (Abbildung 2).

Eine neue dynamische Aktion ...
Abbildung 3: Eine neue dynamische Aktion ...

Im darauf folgenden Dialog wählen Sie Custom als Event-Typen aus und bei Custom Event nehmen Sie aufgabe_kopiert. Bei Selection Type nebmen Sie DOM Object und bei DOM Object tragen Sie document ein. Damit passt diese Dynamic Action ganz genau zum apex.event.trigger-Kommando in obigem JavaScript-Code.

Die dynamische Aktion reagiert auf das Custom Event "aufgabe_kopiert"
Abbildung 4: Die dynamische Aktion reagiert auf das Custom Event "aufgabe_kopiert"

Im dann folgenden Dialog tragen Sie (wie gewohnt) die konkreten Aktionen ein, die beim Auftreten des Events ausgelöst werden sollen. In unserem Beispiel fällt die Aktualisierung (Refresh) des interaktiven Berichts und eine Meldung an den Nutzer (Alert) an. Abbildung 5 zeigt nochmals die wesentlichen Eigenschaften der dynamischen Aktion.

Dynamische Aktion im Überblick
Abbildung 5: Dynamische Aktion im Überblick

Fehlt nun nur noch das tatsächlich auslösende Ereignis. Machen Sie eine Spalte in Ihrem interaktiven Bericht zu einer Link-Spalte. Das Link-Ziel ist vom Typ URL und enthält einen JavaScript-Aufruf: javascript:kopiereAufgabe(#ID#).

Berichtsspalte "AUFGABE" wird zum Link: Bei Klick wird die Zeile kopiert
Abbildung 5: Berichtsspalte AUFGABE wird zum Link: Bei Klick wird die Zeile kopiert

Nun ist alles fertig. Bei Klick auf den Link in der Spalte AUFGABE wird die JavaScript-Funktion kopiereAufgabe() aufgerufen - diese führt einen AJAX-Request durch, wodurch der PL/SQL-Anwendungsprozess gestartet wird, der die Zeile kopiert. Schließlich sendet sie das Event aufgabe_kopiert aus, worauf eine dynamische Aktion reagiert, die dafür sorgt, dass der Bericht aktualisiert wird.

Das Ergebnis: Bei Klick wird die Zeile kopiert
Abbildung 6: Das Ergebnis: Bei Klick wird die Zeile kopiert

Der Vorteil dieser Vorgehensweise liegt auf der Hand: Auf das Ereignis aufgabe_kopiert können nun auch noch andere dynamische Aktionen reagieren - die Aufgabe wurde so weit wie möglich deklarativ gelöst - nur die Dinge, die mit Dynamic Actions nicht machbar sind (Klick in einem Bericht), sind mit JavaScript-Code umgesetzt worden. Man muss sich also nicht zwischen Dynamic Actions und eigenem Code entscheiden - man kann sie vielmehr nahtlos miteinander integrieren.

Zurück zur Community-Seite