Logo Oracle Deutschland   Application Express Community
Drag & Drop in APEX-Anwendungen

Erscheinungsmonat APEX-Version Datenbankversion
Mai 2014 4.0 ab 10.2

In diesem Tipp stellen wir Ihnen vor, wie Sie Drag & Drop in Ihrer APEX-Anwendung realisieren können. Das ist gar nicht so aufwändig, denn das in APEX enthaltene jQuery erledigt den Löwenanteil der Arbeit, so dass nur noch wenige JavaScript-Aufrufe abzusetzen sind. Als Beispiel soll eine APEX-Anwendungsseite mit zwei (klassischen) Berichten dienen. Links steht ein Bericht auf die Tabelle EMP, rechts einer auf die Tabelle DEPT (Abbildung 1). Die Zuordnung zwischen EMP und DEPT-Tabelle soll nun per Drag & Drop änderbar sein.

Ausgangssituation: Berichte auf die Tabellen EMP und DEPT
Abbildung 1: Ausgangssituation: Berichte auf die Tabellen EMP und DEPT

Nun sollte man sich zunächst überlegen, was konkret aus dem linken Bericht in den rechten gezogen werden soll - in Frage kommt die ganze Zeile oder nur eine Spalte. Um zusätzliche Arbeiten am Berichts-Template einzusparen, entscheiden wir uns für die Spalte ENAME - es soll also nur der jeweilige Name gezogen werden. Dazu kann dieser ja hervorgehoben werden. Navigieren Sie also zu den Berichtseinstellungen, dort zu den Einstellungen der Spalte ENAME und dort zum Feld HTML-Ausdruck. Tragen Sie dort folgenden HTML-Code ein.

<div id="emp#EMPNO#" 
     class="draggable_emp">
#ENAME#
</div>

Alle Einträge der Spalte ENAME werden so mit der CSS-Klasse draggable_emp und mit einem ID-Attribut versehen (das wird zum Drag & Drop benötigt). Das gleiche machen Sie dann mit der Spalte DNAME im anderen Bericht. Auch hier wird ein ID-Attribut gebraucht - nehmen Sie aber nun die CSS-Klasse droppable_dept.

<div id="dept#DEPTNO#" 
     class="droppable_dept">
#DNAME#
</div>

Navigieren Sie nun zu den Seitenattributen und hinterlegen Sie bei Inline CSS den CSS-Code für die verwendeten Klassen draggable_emp und droppable_dept. Die dritte CSS-Klasse brauchen wir später noch ...

.draggable_emp {border: 2px solid red; padding: 2px; background-color: #ff8080;}
.droppable_dept {border: 2px solid blue; padding: 2px; background-color: #8080ff;}
.match_dept {border: 2px solid yellow; padding: 2px; background-color: #ffff80;}

Starten Sie die Seite nochmals - sie sollte nun etwa wie in Abbildung 2 aussehen.

Die Drag & Drop-Spalten sind nun hervorgehoben
Abbildung 2: Die Drag & Drop-Spalten sind nun hervorgehoben

Nun aktivieren wir mit Hilfe von jQuery für die roten Kästchen die Eigenschaft draggable. Über die CSS-Klasse draggable_emp können Sie bequem per jQuery-Selektor angesprochen und nach einem Aufruf der jQuery-Methode draggable() mit der Maus bewegt werden. Hinterlegen Sie also - wiederum in den Seitenattributen - im Bereich JavaScript - beim Seitenladen ausführen, die folgenden Codezeilen.

$(".draggable_emp").draggable({
  "containment": "window",
  "helper":      "clone",
  "revert":      "invalid"
});

Nun lassen sich die roten Felder per Maus bewegen. Mit den drei Parametern wurde festgelegt, dass die ENAME-Kästchen über das ganze Browser-Fenster gezogen werden können, dass zum Bewegen eine Kopie erzeugt wird und dass das Element, sofern es nicht auf die blauen DNAME-Kästchen gezogen wird, wieder zum Ausgangspunkt zurückkehren soll. Wenn Sie möchten, können Sie es probieren - derzeit wird das Kästchen aber immer zum Ausgangspunkt zurückkehren, denn es sind ja noch gar keine Ziele (droppables) definiert.

Die roten Kästchen können schon gezogen werden (drag)
Abbildung 3: Die roten Kästchen können schon gezogen werden (drag)

Nun geht es an die Deklaration der Ziele. Die blauen Kästchen werden als droppables definiert und wird wird festgelegt, was passieren soll, wenn ein rotes auf ein blaues Kästchen gezogen wurde. Fügen Sie in den Seitenattributen, dem bereits vorhandenen JavaScript-Code unter Beim Seitenladen ausführen, den folgenden hinzu.

$(".droppable_dept").droppable({
   "accept":     ".draggable_emp",
   "hoverClass": "match_dept",
   drop:         function(event, ui) {
      // set APEX items with drag'n'drop values
      $s("P2_DRAG_EMP", ui.draggable.attr("id").substr(3)); 
      $s("P2_DROP_DEPT", $(this).attr("id").substr(4));
      // trigger event to perform PL/SQL assignment
      apex.event.trigger(
        document, 
        "emp_dragged"
      );
   }
});

Mit Hilfe der jQuery-Methode droppable() werden die blauen Kästchen als Ziele des Drag & Drop deklariert. Damit droppable() genutzt werden kann, müssen Sie noch eine zusätzliche JavaScript-Datei in Ihre Anwendung einbinden. Hinterlegen Sie (immer noch bei den Seitenattributen) die folgende URL im Bereich JavaScript - Datei-URLs.

#IMAGE_PREFIX#libraries/jquery-ui/1.8.22/ui/minified/jquery.ui.droppable.min.js

Der JavaScript-Bereich Ihrer Anwendungsseite sollte danach in etwa wie in Abbildung 4 aussehen.

JavaScript-Einstellungen der Anwendungsseite
Abbildung 4: JavaScript-Einstellungen der Anwendungsseite

Sie können die Seite auch nochmals testen. Sobald Sie ein rotes auf ein blaues Kästchen ziehen, wird das blaue nochmals hervorgehoben. Wenn Sie die Maustaste dann loslassen, wandert das rote Kästchen nicht mehr zum Ausgangspunkt zurück (Abbildung 5). Weiter passiert aber noch nichts.

Die blauen Kästchen "akzeptieren" nun die roten
Abbildung 5: Die blauen Kästchen "akzeptieren" nun die roten

Wenn nun ein rotes auf ein blaues Kästchen gezogen wird, setzt der JavaScript-Code zunächst die APEX-Elemente P2_DRAG_EMP und P2_DROP_DEPT mit den IDs der betroffenen Elemente. Schließlich wird ein APEX-Ereignis (event) namens emp_dragged ausgelöst; auf dieses Event können wir im nächsten Schritt mit einer Dynamic Action reagieren. Da die beiden APEX-Elemente noch nicht existieren, müssen sie nun angelegt werden: Erzeugen Sie also zwei versteckte (Hidden) Elemente, die nicht geschützt sein dürfen (keine Value Protection).

Die Elemente P2_DRAG_EMP und P2_DROP_DEPT wurden erzeugt
Abbildung 6: Die Elemente P2_DRAG_EMP und P2_DROP_DEPT wurden erzeugt

Erzeugen Sie dann eine neue Dynamic Action namens Reassign EMP. Abbildung 7 zeigt Ihnen die Einstellungen zum Event, auf welches die dynamische Aktion reagieren soll.

Die dynamische Aktion reagiert auf das Custom-Event "emp_dragged"
Abbildung 7: Die dynamische Aktion reagiert auf das Custom-Event "emp_dragged"

Machen Sie die Einstellungen genau so, wie in Abbildung 7 gezeigt: Nehmen Sie ein Custom Event. Tragen Sie emp_dragged als Namen des Events ein. Legen Sie DOM Object als Selection Type fest und tragen Sie document als DOM-Objekt ein. So korrespondiert die dynamische Aktion exakt mit dem Aufruf von apex.event.trigger im JavaScript-Code. Abbildung 8 zeigt Ihnen die Einstellungen zur konkreten Aktion, die APEX durchführen soll, wenn das Ereignis eintritt.

Beim Eintritt des Ereignis soll PL/SQL-Code ausgeführt werden
Abbildung 8: Beim Eintritt des Ereignis soll PL/SQL-Code ausgeführt werden
begin
  update emp set deptno = :P2_DROP_DEPT where empno = :P2_DRAG_EMP;
end;

Der auszuführende PL/SQL-Code ist sehr einfach: Es wird einfach ein UPDATE auf die Tabelle EMP gemacht. Anhand der IDs der roten und blauen Kästchen können EMPNO und DEPTNO gesetzt werden. Vergessen Sie nicht, beide APEX-Elemente bei Page Items to Submit einzutragen. Klicken Sie dann auf Weiter und erzeugen Sie schließlich die dynamische Aktion.

Bevor Sie nun aber Ihre Seite testen, klicken Sie nochmals mit der rechten Maustaste auf die neue dynamische Aktion und fügen Sie eine weitere TRUE Action hinzu - denn wir möchten nach erfolgreicher Neu-Zuordnung noch den linken Bericht aktualisieren (Abbildung 9).

Weitere TRUE Action ...
Abbildung 9: Weitere TRUE Action ..."

Abbildung 10 zeigt, was zu tun ist. Wählen Sie Refresh als Aktion aus und legen Sie die Region mit dem Bericht auf die EMP-Tabelle als betroffenes Element fest. Nach einem Klick auf Erstellen bzw. Create und dann nochmals auf Apply Changes sind Sie auch schon fertig.

... zum Aktualisieren des Berichts auf die Tabelle EMP
Abbildung 10: ... zum Aktualisieren des Berichts auf die Tabelle EMP

Starten Sie die Seite nun nochmals. Ziehen Sie ein rotes auf ein blaues Kästchen, um so einen EMP einem DEPT zuzuweisen. Sobald Sie das Kästchen losgelassen haben, findet die UPDATE-Aktion statt und der linke Bericht wird neu geladen, so dass Sie das Ergebnis sofort sehen können. Allerdings funktioniert es nur einmal; danach können Sie die roten Kästchen nicht mehr mit der Maus ziehen ...

... wofür es einen einfachen Grund gibt: Mit dem Aktualisieren des Berichts ist die Eigenschaft Draggable der roten Kästchen verlorengegangen - denn die Berichtsdaten wurden neu vom Server geladen. Der ganz zu Beginn ausgeführte JavaScript-Aufruf der jQuery-Methode draggable() muss also nochmals geschehen. Dazu dient die letzte Dynamic Action, die wir jetzt erzeugen:

  • Erzeugen Sie eine neue Dynamic Action namens Wiederherstellen Draggable .
  • Nehmen Sie das Ereignis After Refresh und wählen Sie die Region mit dem Bericht auf die Tabelle EMP aus.
  • Nehmen Sie Execute JavaScript-Code als Aktion und hinterlegen Sie den folgenden JavaScript-Code.
    $(".draggable_emp").draggable({
      "containment": "window",
      "helper":      "clone",
      "revert":      "invalid"
    });
    
  • Entweder entfernen Sie das Häkchen bei Exceute on Page Load oder Sie lassen es stehen, nehmen diese fünf Zeilen dann aber aus dem Bereich der Seitenattribute (wo er eingangs hinterlegt wurde) wieder heraus - sonst wird er beim Page Load doppelt ausgeführt.

Nun sind Sie wirklich fertig. Sie können die Zeilen aus EMP nun beliebig häufig auf die Zeilen von DEPT ziehen, was zu einer Neu-Zuordung führt. Basierend auf diesem Beispiel können Sie nun natürlich auch andere Aufgaben per Drag & Drop umsetzen.

Zurück zur Community-Seite