Drag & Drop Operationen in einer Tabelle mit Web Dynpro ABAP
In diesem How To werden Ihnen die verschiedenen Möglichkeiten der Drag & Drop-Operationen für das Web Dynpro ABAP UI-Element “Table” vorgestellt. Anhand einer Web Dynpro Anwendungen werden verschiedene Szenarien präsentiert und die Vorgehensweise erklärt.
Drag & Drop bezeichnet eine Benutzeraktion, in der der Nutzer ein Element aus einer Quelle auf ein Zielelement zieht und dort platziert. Dies geschieht typischer Weise mit der Maus.
In Web Dynpro ABAP kann man diese Funktionalität ebenfalls umsetzen. Hierfür eignen sich fast alle UI-Elemente und selbst solche, die ungeeignet erscheinen, können mit Hilfe des sogenannten DropTarget UI-Element “Drag&Drop-fähig” gemacht werden. In diesem Beispiel wird jedoch nur auf das UI-Element Table eingegangen.
Die Tabelle bietet folgende Drag & Drop-Operationen an:
- Einfügen von neuen Zeilen
- Verschieben von Zeilen in der Tabelle
- Zeilen-Drop, sprich es wird ein “Drop” auf eine Zeile ermöglicht
Wichtig ist zwischen Ziel und Quelle zu unterscheiden. Die Quelle definiert eine sogenannte DragSourceInfo. Diese ermöglicht über die Eigenschaft data Daten an das Ziel der Drag & Drop-Operation zu übergeben. Das Ziel-Element definiert eine DropTargetInfo, welche das Event onDrop auslöst, wenn ein Element auf das Ziel fallen gelassen wird.
Ziel und Quelle werden über die Eigenschaft tag verbunden, indem dort dieselben Bezeichner gepflegt werden.
In dem ersten Beispiel wird eine Tabelle implementiert, welche die Quelle der Drag & Drop-Operation darstellt. Das Ziel der Operation ist eine Form, welche sich abhängig von der Tabellenzeile, die auf die Form fallen gelassen wird, füllt.
An diesem Punkt wird angenommen, dass Sie sich mit der grundlegenden Architektur eines Web Dynpros auskennen.
Sie haben eine Web Dynpro Anwendung mit einer Tabelle und einer Form. In meinem Fall ist es, um das Beispiel so simpel wie möglich zu halten die Tabelle SFLIGHT, also die Flugtabelle vom SAP IDES.
Der Context ist im Component-Controller gepflegt? Wurde dieser mit der View gemappt und mit den entsprechenden UI-Elementen gebunden? Dann kann es jetzt losgehen.
Mein Context sieht folgendermaßen aus:
Um die Tabelle als Quelle einer Drag & Drop-Operation zu definieren gehen Sie in die View und selektieren mit Rechtsklick auf das Table-Element Drag-Source einfügen
Nun können sie die Eigenschaften der DragSourceInfo pflegen. In meinem Beispiel übergebe ich die eindeutige Flugnummer über die Eigenschaft data und als tag benutze ich “TABLE”. Dieser tag wird genutzt um Quelle und Ziel miteinander zu verbinden.
Als nächsten Schritt legen sie ein DropTarget-Element
an um Ihre Form als Ziel für Ihre Drag-&-Drop-Operation festzulegen.
Dieses UI-Element verfügt über das Ereignis onDrop. Sie können einen Ereignisbehandler implementieren, welcher ausgelöst wird, wenn ein Element auf dieses DropTarget fallen gelassen wird.
In dieses DropTarget fügen Sie nun eine Form ein. Das Element kann nur ein UI-Element enthalten aber dies kann ja mit Hilfe eines Transparent-Container umgangen werden.
Im nächsten Schritt wird dieses DropTarget mit einem DropTargetInfo
versehen, in dem die Eigenschaften für das Ziel der Drag & Drop-Operation definiert werden.
Der tag muss identisch zu dem aus der Quelle sein. Es kann auch ein Teil des Namens verwendet werden, da mit Wildcards (*) gearbeitet werden kann.
Als letzter Schritt muss nun die Logik für den onDrop-Eventhandler implementiert werden.
METHOD onactionflight_dropped .
DATA lo_nd_flight_number TYPE REF TO if_wd_context_node.
DATA ls_flights TYPE sflight.
DATA lv_free_seats TYPE sflight–seatsocc.
DATA lo_el_flight_number TYPE REF TO if_wd_context_element.
DATA ls_flight_number TYPE wd_this->element_flight_number.
DATA lv_connid TYPE wd_this->element_flight_number–connid.
DATA lo_nd_flight_info TYPE REF TO if_wd_context_node.
DATA lo_el_flight_info TYPE REF TO if_wd_context_element.
DATA ls_flight_info TYPE wd_this->element_flight_info.
lv_connid = data.
lo_nd_flight_number = wd_context->get_child_node( name = wd_this->wdctx_flight_number ).
lo_el_flight_number = lo_nd_flight_number->get_element( ).
lo_el_flight_number->set_attribute(
name = `CONNID`
value = lv_connid ).
SELECT SINGLE seatsmax seatsocc FROM sflight INTO CORRESPONDING FIELDS OF ls_flights
WHERE connid = data.
lv_free_seats = ls_flights–seatsmax – ls_flights–seatsocc.
lo_nd_flight_info = wd_context->get_child_node( name = wd_this->wdctx_flight_info ).
lo_el_flight_info = lo_nd_flight_info->get_element( ).
ls_flight_info–seatsmax = ls_flights–seatsmax.
ls_flight_info–seatsocc = lv_free_seats.
lo_el_flight_info->set_static_attributes(
static_attributes = ls_flight_info ).
ENDMETHOD.
Die freien Plätze werden mit der übergebenen Flugnummer berechnet und damit die Attribute der Forn im Context gesetzt.
Nachdem Sie eine Web Dynpro Anwendung erstellt haben, können Sie die Funktionalität im Browser testen. Hiermit wäre der erste Fall abgeschlossen.
Im nächsten Fallbeispiel wird auf die Unterschiede zu dem vorherigen Drag & Drop-Beispiel eingegangen.
Die Felder der Form füllen sich.
Im nächsten Fall implementieren wir das Einfügen neuer Zeilen in einer Tabelle und das Verschieben vorhandener Zeilen in zugehörigen Tabelle.
Hierfür wird der bestehenden Logik eine neue Tabelle hinzugefügt. Hier wird die Tabelle SBOOK als Vorbild genommen. Sie müssen im Context einen neuen Knoten anlegen und diesen mit der View mappen.
Diese Tabelle soll nun Einträge der ersten Tabelle aufnehmen können und auch ermöglichen, eigene Zeilen zu verschieben oder umzusortieren.
Hierfür müssen Sie folgende Schritte ausführen:
- DragSourceInfo hinzufügen
- DropTargetInfo hinzufügen
- Die tags für die entsprechenden Tabellen richtig pflegen, d.h. für das target den tag von der ersten Tabelle also “TABLE” und für den DropOnRowTargetInfos einen eigenen tag, welcher dann auch für den DragSourceInfo verwendet wird.
- Das onDrop Event behandeln
In der Methode kann über den tag, welcher ein Import-Parameter ist, abgefragt werden, welche DragSource gerade das Event ausgelöst hat. Daher ist es wichtig diese eindeutig zu vergeben, damit man in Fällen wie diesem, wo mehrere DragSourceInfos auf die Tabelle verweisen, unterscheiden kann, welche Ereignisbehandlung aufgerufen werden soll.
Es bietet sich an, Konstanten für die Tags anzulegen. Da es sich hier nur um ein kleines Beispiel handelt, werden sie direkt in den Code geschrieben.
Fügen Sie den Code in Ihren Ereignisbehandler ein, um das Beispiel abzuschließen.
METHOD onactiontable_drop .
DATA lo_nd_booking_table TYPE REF TO if_wd_context_node.
DATA lo_lead_selection TYPE REF TO IF_WD_CONTEXT_ELEMENT.
DATA lt_booking_table TYPE wd_this->elements_booking_table.
DATA ls_booking TYPE wd_this->element_booking_table.
DATA ls_selected_entry TYPE wd_this->element_booking_table.
DATA ls_spfli TYPE spfli.
DATA lv_index TYPE i.
IF tags = ‘TABLE’.
SELECT SINGLE * FROM spfli INTO CORRESPONDING FIELDS OF ls_booking WHERE connid = data.
APPEND ls_booking TO lt_booking_table.
lo_nd_booking_table = wd_context->get_child_node( name = wd_this->wdctx_booking_table ).
lo_nd_booking_table->bind_table( new_items = lt_booking_table set_initial_elements = abap_false ).
ELSEIF tags = ‘ROW’.
lo_nd_booking_table = wd_context->get_child_node( name = wd_this->wdctx_booking_table ).
lo_nd_booking_table->get_static_attributes( IMPORTING static_attributes = ls_selected_entry ).
lo_nd_booking_table->get_static_attributes_table( IMPORTING table = lt_booking_table ).
lo_lead_selection = lo_nd_booking_table->get_lead_selection( ).
lv_index = lo_lead_selection->get_index( ).
IF lv_index = 0.
lv_index = 1.
ENDIF.
DELETE lt_booking_table INDEX lv_index.
lv_index = row_element->get_index( ).
INSERT ls_selected_entry INTO lt_booking_table INDEX lv_index.
lo_nd_booking_table->bind_table( new_items = lt_booking_table set_initial_elements = abap_true ).
lo_nd_booking_table->move_to( index = lv_index ).
ENDIF.
ENDMETHOD.
Erklärung des Codings:
Über den Import Parameter ROW_ELEMENT wird eine Referenz auf die Zeile, auf die man die ausgewählte Tabellenzeile “fallen gelassen” hat, übergeben. Über die Methode get_index( ) liefert die aktuelle Position der Zeile in der Tabelle. Die lead_selection wird ausgelesen, dies ist die selektierte Zeile in der Tabelle, die bewegt werden soll. Diese werden aus der Tabelle gelöscht, und wieder an dem neuen Index eingefügt. Zuletzt wird die neue Lead Selection der Tabelle mit der Methode move_to( ) an den neuen Index verschoben. Diese Methode stellt das Interface IF_WD_CONTEXT_NODE, also in diesem Fall die Referenz auf den Context-Knoten der zweiten Tabelle.
Das Ergebnis der Erweiterungen sieht so aus:
Vorgang mit anderen Zeilen wiederholen
Nun unterste Zeile nach oben ziehen
Ergebnis
Ich hoffe Ihnen hat dieses How To gefallen und Sie haben lernen können, wie die Drag & Drop-Operationen für das Web Dynpro UI-Element Table umzusetzen sind. Falls es Sie noch interessiert, wie ein Drag & Drop auf eine Zeile umzusetzen ist, nutzen Sie unsere Kommentarfunktion, wir helfen Ihnen gerne weiter
Für Fragen rund um das Thema dieses Blogbeitrages stehe ich Ihnen gerne zur Verfügung.
6 Kommentare zu "Drag & Drop Operationen in einer Tabelle mit Web Dynpro ABAP"
Hallo Herr Bianchini!
Vielen Dank für die Informationen zu Drag & Drop. Ich suche nach einer Möglichkeit einen Drop in eine Tabellenspalte zu realisieren, komme da aber nicht wirklich voran. Haben Sie vielleicht eine Idee dazu?
Mit freundlichen Grüßen
Martin Tilenius
Hallo Herr Tilenius,
sehr gerne! Danke für Ihr Interesse an dem Artikel.
Also von Haus aus bietet SAP einige Optionen für die Manipulation von Tabellen durch Drag & Drop Tabellen.
1. Das Einfügen neuer Zeilen zwischen bereits vorhandenen Tabellenzeilen
2. Einfügen an erster oder letzter Position innerhalb der aufgelisteten Zeilen
3. Auf eine bereits existierende Zeile
Option 3 ist für Sie interessant.
Ich werde Ihnen nun kurz beschreiben, wie Sie vorgehen sollten, um in eine bestehende Zeile zu “droppen”.
Benötigte Schritte:
Es verhält sich eigentlich relativ ähnlich wie das Einfügen neuer Zeilen zu einer Tabelle.
Öffnen Sie via Rechtsklick das Kontextmenü Ihrer betreffenden Tabelle. Dort befindet sich der Eintrag “INSERT DROP_ROW_TRG_INF (dropOnRowTargetInfos). Bitte wählen Sie diesen aus. (Durch diesen Schritt wird eine DropTargetInfo erstellt.) Alternativ kann hier auch eine bestehende DropTargetInfo verwendet werden.
Füllen Sie für das neue Element bitte die nötigen Informationen aus. Die Eigenschaft “name” wird in einem späteren Schritt wieder benötigt, also bitte einen Wert pflegen.
In Ihrer Tabelle gibt es eine Eigenschaft “dropOnRowName”, hier geben Sie den Name der zuvor definierten DropTargetInfo an.
Nun können Sie in dem Ereignis “onDrop” die nötige Logik implementieren um das Element, was Sie per Drag&Drop auf die Zeile gezogen haben einer Spalte hinzuzufügen.
Die Einfügeposition können Sie mit Hilfe der Methode “get_index” des Interfaces IF_WD_CONTEXT_ELEMENT und dem OFFSET-Attribut ermitteln. Das OFFSET-Attribut wird in dem Ereignis onDrop übergeben.
Ich hoffe ich konnte Ihnen helfen, damit Sie Ihr Problem lösen können.
Mit freundlichen Grüßen
Sebastian Bianchini
Hallo Herr Bianchini,
interessanter Beitrag!
Ich habe eben bei google nach “web dynpro abap table drag and drop” gesucht und habe Ihren Beitrag auf Platz 1 gelistet bekommen – Respekt!
Eigentlich ist für meine aktuelle Aufgabenstellung, nur das Verschieben von Zeilen innerhalb einer Tabelle von Bedeutung. Daher habe ich mir nur Methode “onactiontable_drop” genauer angesehen. Funktioniert prima!
Aufgabe von “onactiontable_drop( )” ist es doch, ein Element des Knotens von einem Index auf einen anderen zu verschieben. Also interessieren uns die Daten der Elemente gar nicht:
[…]
ELSEIF tags = ‘ROW’.
lo_nd_booking_table = wd_context->get_child_node( … ).
lo_nd_booking_table->move_element( from = lo_nd_booking_table->get_element( )->get_index( ) to = row_element->get_index( ) ).
ENDIF.
[…]
Hallo Herr El-Arnaouty,
vielen Dank für Ihr Lob und es freut mich, dass Ihre Aufgabe durch den Blogbeitrag gelöst werden konnte.
In meinem Beispiel lese ich die Tabelle aus dem Kontext aus, verändere den Inhalt, binde Sie wieder an den Kontextknoten und setze die Leadselection neu um.
Viele Grüße und weiterhin viel Erfolg,
Sebastian Bianchini