Drag & drop w AngularJS

Chcemy, aby z naszej aplikacji korzystało się jak najszybciej i jak najwygodniej. Dzięki temu poprawiamy produktywność i wpływamy na pozytywne doświadczenia użytkownika podczas korzystania z aplikacji (ang. User experience, UX).

Możemy do aplikacji dodać mechanizm przeciągnij i upuść (ang. drag and drop). Zastosujemy go w aplikacji AgendaEditor, aby można było łatwo zmieniać kolejność wystąpień. Oczywiście moglibyśmy dodać przyciski, po których kliknięciu, wystąpienie przesuwałoby się w górę lub w dół. Ale będzie to wyglądało lepiej, jeżeli będziemy mogli je po prostu przeciągnąć.

Biblioteki drag & drop

Możemy w JavaScript sami zaimplementować taką funkcjonalność. Ale po co wymyślać koło na nowo. Ktoś już to dawno zrobił, dopracował i udostępnił, aby inni mogli skorzystać. Jeżeli kogoś by to jednak zainteresowało, to może poczytać o tym np. tutaj.

Znalazłem fajną bibliotekę dla AngularJS: angular-drag-and-drop-lists (demo). Ma wiele możliwości, dobre przykłady użycia i jest łatwa w użyciu. Dokładnie to czego potrzebuję. Jednak ma jedną, dużą wadę. Domyślnie nie działa na urządzeniach mobilnych (testowałem na Androidzie i rzeczywiście nie działa):

Touch devices are not supported, because they do not implement the HTML5 drag & drop standard. However, you can use a shim to make it work on touch devices as well.

Oczywiście jest więcej bibliotek np.

A tutaj można znaleźć spis jeszcze innych bibliotek dla drag&drop: Best AngularJs Drag & Drop Directives Plugins.

Jest jeszcze jedna biblioteka: Dragula, którą wykorzystam. Jej zaletą jest to, że działa na urządzeniach mobilnych (testowałem na Androidzie). Jest dosyć nowa i świeża, ale działa prawidłowo.

Dziękuję mik-laj z GitHuba za podpowiedź odnośnie biblioteki Dragula, bo tej jeszcze nie znałem, a jest dosyć dobra (swoją drogą dostałem pierwszy pull request do projektu; zajmę się nim po zakończeniu konkursu).

Dragula

Dostępna jest w wersji JavaScript: https://github.com/bevacqua/dragula
Ale dostępny jest takze wrapper pod AngularJS (wersja przystosowana, żeby można było jej łatwiej użyć w Angularze): https://github.com/bevacqua/angular-dragula/
Demo można znaleźć tutaj: http://bevacqua.github.io/angular-dragula/

Dodanie Draguli do projektu

Aby dodać pliki biblioteki do naszej aplikacji, możemy je ściągnąć z GitHuba z katalogu dist. A jeśli chcemy dodać link do zewnętrznego serwera, możemy skorzystać z serwerów CDN. Musimy dodać plik angular-dragula.js oraz dragula.css. Do wyboru mamy wersję zwykłą i zminifikowaną (z końcówką min).

W pliku index.html w sekcji <head> doklejamy linki do biblioteki:

Oczywiście musimy pamiętać o odpowiedniej kolejności dodawania plików. Najpierw dodajmy pliki CSS, następnie pliki JavaScript: jQuery, Bootstrapa, Angulara, tutaj bibliotekę do Angulara i na końcu pliki z naszymi kontrolerami.

Konfiguracja Draguli

W pliku konfiguracyjnym naszej aplikacji app.js mamy linijkę definiującą aplikację i moduły wstrzyknięte do niej:

Musimy dodać zależność: angularDragula(angular). Oczywiście poprzednie zależności (w nawiasach kwadratowych) jakie mamy zostawiamy, tylko po przecinku dodajemy kolejną. Będzie to wyglądać tak:

Teraz możemy już skorzystać z Draguli.

Modyfikacja szablonu HTML

Skorzystamy z udostępnionych dyrektyw, aby uruchomić Dragulę. Zadanie mamy ułatwione, gdyż dobrze zaprojektowaliśmy naszą aplikację. Dane wystąpień są dostępne na liście agenda.list (pobierana z naszego serwisu). Na niej będzie operować Dragula.

Mieliśmy taką tabelę w pliku home.html:

Musimy dodać dyrektywy:

  • dragula='"bag-one"', mówi nam, który element będzie miejscem do przeciągania elementów (moze być ich kilka, my jednak potrzebujemy jednego),
  • dragula-model="agenda.list", podajemy na jakiej liście ma operować (przenosić w niej elementy),
  • dragula-scope='$parent', ta dyrektywa jest potrzebna, żeby Angular odnalazł właściwy $scope (bez tego upuszczanie elementów nie działa poprawnie, nie lądują w odpowiednim pojemniku). Umieszczamy ją w elemencie, który ma być przenoszony (czyli tym samym, w którym jest ng-repeat).

Te dyrektywy musimy dodać w elemencie nadrzędnym, które chce chcemy przeciągać (chcemy przeciągać wiersze <tr>). Umieścilibyśmy dyrektywy Draguli w elemencie <table>, ale nie chcemy włączać przeciągania dla nagłówków. Dlatego dodamy kolejny element <tbody> grupujący zawartość tabeli bez nagłówków (dla nich jest odpowiedni element <thead>, który przy okazji możemy dodać).

Nasz tabela powinna teraz wyglądać tak:

Aplikacja z drag & drop

Po dodaniu biblioteki Dragula, skonfigurowaniu i modyfikacji tabeli (dodaniu dyrektyw), przeciąganie i upuszczanie dla wystąpień działa. Zauważmy, że zmiany są wykonywane na bieżąco, a wynikowy tekst agendy jest modyfikowany od razu po przeciągnięciu (również godziny są obliczane). Jak widzimy nie było to trudne, a daje dobry efekt.

Podgląd działającej aplikacji (lub otwórz w nowej karcie lub edytor Plunker):

Pamiętajmy, że możemy wkleić przykładowe dane w zakładce import, aby móc szybko przetestować działanie:

Programowanie	Jan	Kowalski	00:20
AngularJS	Anna	Nowak	00:25
JavaScript	Janusz	Programista	00:15

Trzeba tylko dopisać godzinę rozpoczęcia np. 15:00 i możemy przeciągać wystąpienia.

Kod aplikacji, jak zawsze, dostępny na Githubie: https://github.com/mkczyk/agenda-editor

One response on “Drag & drop w AngularJS

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *