Jobs
Ein Blick unter die Wolkendecke
Sencha Know How 14.11.2017

Developer Tip of the Month: "Drag And Drop Basics"

ExtJS bietet eine sehr übersichtliche und einfache Implementierung von "Drag and Drop" (DnD) für Ihre Web-Applikationen. In diesem Beitrag werden Sie erfahren, wie "DnD" funktioniert und wie es verwendet werden kann.

Eine "Drag-Operation" wird durch einen Klick auf ein UI-Element und anschließendem Bewegen der Maus, während diese gedrückt und gehalten wird, ausgelöst.
Eine "Drop-Operation" wird ausgelöst, sobald die Maustaste nach einer "Drag-Operation" losgelassen wird.

Für den Benutzer ist die Verwendung von "Drag&Drop" sehr intuitiv und damit ein gutes Werkzeug, um bestimmte Workflows oder bestimmte Aufgaben benutzerfreundlich und effizient zu gestalten.

Im Folgenden wird die Funktionsweise an Hand eines Beispiels veranschaulicht. Darin verwenden wir einen Hauptcontainer, welcher mehrere Kind-Container (DataViews) beinhaltet. 

Ziel ist es, ein Element grafisch per "DnD" von einem Container in einen anderen verschieben zu können, und dass dieser aus seinem ursprünglichen Store (Quelle) entfernt und dem "Ziel"-Store hinzugefügt wird.

//DataView Klasse (subcontainer)
Ext.define('myColumn', {
    extend: 'Ext.view.View',
    xtype: 'mycolumn',
    .....
    itemSelector: 'div.nameselector',
    tpl: [
        '<tpl for=".">',
          '<div class="nameselector<tpl if="isTemp"> temp</tpl>">', '{name}', '</div>',
        '</tpl>'
    ]
});


//Hauptcontainer 
Ext.create('Ext.panel.Panel', {
    renderTo: Ext.getBody(),
    plugins: 'viewport',

    layout: {
        type: 'hbox',
        align: 'stretch'
    },

    items: [{
        xtype: 'mycolumn',
        ...
    }, {
        xtype: 'mycolumn',
        ...
    }, {
        xtype: 'mycolumn',
        ...
    }, {
        xtype: 'mycolumn',
        ...
    }]
})

Definition von Dragzone und Dropzone:

Die "Dragzone" ist der Bereich, aus welchem das Element entnommen wird und die "Dropzone" ist der Bereich, in welchem das Element abgelegt wird.
Die entsprechenden Instanzen von Ext.dd.DragZone und Ext.dd.DropZone dürfen erst nach dem Rendering der Container erzeugt werden.
Das Beispiel zeigt, dass es möglich ist, "Dragzone" und "Dropzone" auf dem selben Container zu erzeugen.
Das Beispiel beschreibt, dass jede Datenansicht eine "Dragzone", aber auch eine "Dropzone" ist.


Die "Drag&Drop-Aktion" gliedert sich in drei Phasen:

  1. Sich mit der Maus auf das Objekt bewegen und dieses auswählen. 
  2. "Drag" das Objekt an die gewünschte Stelle ziehen.
  3. "Drop" das Objekt an der gewünschten Stelle loslassen.

listeners: {
    render: function(me) {
        var tempRec = null;

        // drag zone (Bereich, aus dem die Elemente entnommen werden)
        this.dragZone = new Ext.dd.DragZone(me.getEl(), {
            // Bei einem Mousedown-Ereignis, prüfen, ob es sich innerhalb eines DataView-Knotens befindet.
            // Wenn ja, dann Drag-Datenobjekt zurückgeben
            getDragData: function(e) {
                .....
            },
            getRepairXY: function() {
                ....
            }
        });

        // Drop zone (Bereich, in dem die Elemente abgelegt werden)
        this.dropZone = new Ext.dd.DropZone(me.getEl(), {
            // Hilfsmethode zur Rückgabe ob Drop erlaubt ist oder nicht
            getAllowed: function(allowed) {
                ...
            },

            // Icon Ausgabe bei Edit
            notifyOver: function(source) {
                ...
            },

            // Wird aufgerufen, wenn das Element über einer Dropzone liegt (Drag over)
            // temp Record zum Store hinzufügen
            notifyEnter: function(source, e, data) {
                ...
            },

            // Wird aufgerufen, wenn Element die Dropzone verlässt
            // temp Record aus dem Store entfernen
            notifyOut: function(source, e, data) {
                ....
            },

            // Drop-style setzen
            onContainerOver: function(source, e, data) {
                ...
            },

            // prüft, ob Element über derselben Spalte
            onContainerDrop: function(source, e, data) {
                .....
            }
        });
    }
}

Lauffähiges Beispiel als Fiddle.

Zurück