7

what i want to do is exactly this , but that is in jQuery and i want to know if is there a way to do that in AngularJS, or if someone has alredy done it with the Angular way, and if not, how it suppouse that Angular allows you to customize directives to solve this kind of problems.

I know to use jQuery but i want to move on into AngularJS and its very confusing, so i'm sorry if my question isn't good enough, but all what i've found is this and that doesn't help at all. I'd really apreciate any advice you can say me about this.

Community
  • 1
  • 1
Ruben Marrero
  • 1,392
  • 1
  • 10
  • 23
  • hey just saying, you don't have to force it and **don't use** jQuery at all. I think AngularJs could be used with jQuery with not problems! For example for a thing like this – Gonz Feb 25 '14 at 00:19
  • @GonzaloNaveira Ok thanks, but lets say that i want to use those draggable jQuery elements as the template of a directive, just by doing what is told in this [video](http://www.youtube.com/watch?v=Yg-R1gchccg&index=3&list=PL173F1A311439C05D) would it work fine? – Ruben Marrero Feb 25 '14 at 00:28
  • For ex, if you declare your directive then in jQuery you culd access it $('someting'). That's help you? – Gonz Feb 25 '14 at 00:31
  • Well, if it works, then yes but i had doubts about if that could work. (i'm just doing my very first steps with AngularJS). – Ruben Marrero Feb 25 '14 at 00:33
  • Drag and drop without jQuery: http://www.directiv.es/Angular-DragDrop – Chris Ritchie Nov 06 '14 at 12:05

3 Answers3

12

Here is how I did it, it is a little more complicated, since I included the ability to add event handlers (start, drag, stop), and a container element. Here is a working fiddle for demonstration JSFiddle Without jQuery. Here is another fiddle with a version using jQuery and jQueryUI [JSFiddle w/ jQuery]. Hope it helps. JSFiddle With jQuery and jQueryUI.

You can use it like this

ng-draggable='dragOptions'

where in your controller you have

$scope.dragOptions = {
    start: function(e) {
      console.log("STARTING");
    },
    drag: function(e) {
      console.log("DRAGGING");
    },
    stop: function(e) {
      console.log("STOPPING");
    },
    container: 'container-id'
}

Here is the directive.

.directive('ngDraggable', function($document) {
  return {
    restrict: 'A',
    scope: {
      dragOptions: '=ngDraggable'
    },
    link: function(scope, elem, attr) {
      var startX, startY, x = 0, y = 0,
          start, stop, drag, container;

      var width  = elem[0].offsetWidth,
          height = elem[0].offsetHeight;

      // Obtain drag options
      if (scope.dragOptions) {
        start  = scope.dragOptions.start;
        drag   = scope.dragOptions.drag;
        stop   = scope.dragOptions.stop;
        var id = scope.dragOptions.container;
        container = document.getElementById(id).getBoundingClientRect();
      }

      // Bind mousedown event
      elem.on('mousedown', function(e) {
        e.preventDefault();
        startX = e.clientX - elem[0].offsetLeft;
        startY = e.clientY - elem[0].offsetTop;
        $document.on('mousemove', mousemove);
        $document.on('mouseup', mouseup);
        if (start) start(e);
      });

      // Handle drag event
      function mousemove(e) {
        y = e.clientY - startY;
        x = e.clientX - startX;
        setPosition();
        if (drag) drag(e);
      }

      // Unbind drag events
      function mouseup(e) {
        $document.unbind('mousemove', mousemove);
        $document.unbind('mouseup', mouseup);
        if (stop) stop(e);
      }

      // Move element, within container if provided
      function setPosition() {
        if (container) {
          if (x < container.left) {
            x = container.left;
          } else if (x > container.right - width) {
            x = container.right - width;
          }
          if (y < container.top) {
            y = container.top;
          } else if (y > container.bottom - height) {
            y = container.bottom - height;
          }
        }

        elem.css({
          top: y + 'px',
          left:  x + 'px'
        });
      }
    }
  }

})
Zack Argyle
  • 8,057
  • 4
  • 29
  • 37
  • Thanks, could you also add a link where it documents how to learn to customize directives in that way? (may be the one, or ones where you learnt it) Even if not, is very helpfull your answer. – Ruben Marrero Feb 25 '14 at 01:15
  • 1
    @jCuga, I added a fiddle for you. Let me know if you have any questions. – Zack Argyle Feb 25 '14 at 04:02
  • 1
    @VdeVatman, I would assume so. You could add say elem.on('mousedown touchstart'), bind('mousemove touchmove') and bind('mouseup touchend'), and then unbind the same. Then make sure to include the angular-touch.js module in your application. – Zack Argyle Feb 25 '14 at 15:09
  • I would love to see the option to resize the element :) – handsome Apr 13 '16 at 23:44
  • @ZackArgyle Thanks for sharing this. Is there anyway to save the x and y axis in the scope perhaps? Like what if I wanted to show in the screen the x and y axis from the new position? Sorry quite new to Angular. More power to you and thanks in advance. :) – Annie Lagang Dec 09 '16 at 02:58
6

Best example of Drag and Drop using AngularJS. Designed with easy steps.

First of all define anguler application (ng-app) name, define two directives and one controller as mentioned below. Also apply some css which will improve a look and feel of html

Just run the snippet and enjoy the coding.

var module = angular.module('my-app', []);

module.directive('draggable', function () {
  return {
    restrict: 'A',
    link: function (scope, element, attrs) {
      element[0].addEventListener('dragstart', scope.handleDragStart, false);
      element[0].addEventListener('dragend', scope.handleDragEnd, false);
    }
  }
});

module.directive('droppable', function () {
  return {
    restrict: 'A',
    link: function (scope, element, attrs) {
      element[0].addEventListener('drop', scope.handleDrop, false);
      element[0].addEventListener('dragover', scope.handleDragOver, false);
    }
  }
});

function MainController($scope)
{
    $scope.drag_types = [
        {name: "Charan"},
        {name: "Vijay"},
        {name: "Mahesh"},
      {name: "Dhananjay"},
    ];
    $scope.items = [];
    
    $scope.handleDragStart = function(e){
        this.style.opacity = '0.4';
        e.dataTransfer.setData('text/plain', this.innerHTML);
    };
    
    $scope.handleDragEnd = function(e){
        this.style.opacity = '1.0';
    };
    
    $scope.handleDrop = function(e){
        e.preventDefault();
        e.stopPropagation();
        var dataText = e.dataTransfer.getData('text/plain');
        $scope.$apply(function() {
            $scope.items.push(dataText);
        });
        console.log($scope.items);
    };
    
    $scope.handleDragOver = function (e) {
        e.preventDefault(); // Necessary. Allows us to drop.
        e.dataTransfer.dropEffect = 'move';  // See the section on the DataTransfer object.
        return false;
  };
           
}
.container {
  width: 600px;
  border: 1px solid #CCC;
  box-shadow: 0 1px 5px #CCC;
  border-radius: 5px;
  font-family: verdana;
  margin: 25px auto;
}

.container header {
  background: #f1f1f1;
  background-image: -webkit-linear-gradient( top, #f1f1f1, #CCC );
  background-image: -ms-linear-gradient( top, #f1f1f1, #CCC );
  background-image: -moz-linear-gradient( top, #f1f1f1, #CCC );
  background-image: -o-linear-gradient( top, #f1f1f1, #CCC );
  box-shadow: 0 1px 2px #888;
  padding: 10px;
}

.container h1 {
  padding: 0;
  margin: 0;
  font-size: 16px;
  font-weight: normal;
  text-shadow: 0 1px 2px white;
  color: #888;
  text-align: center;
}

.container section {
  padding: 10px 30px; 
  font-size: 12px;
  line-height: 175%;
  color: #333;
}
<script src="http://code.angularjs.org/1.2.13/angular.js"></script>
<div ng-app="my-app" ng-controller="MainController">
    <div class="container">
        <header><h1>Drag students from here</h1></header>
        <section>
            <div draggable="true" ng-repeat="drag_type in drag_types">{{drag_type.name}}</div>
        </section>
    </div>
    <div class="container">
        <header><h1>Drop students here</h1></header>
        <section droppable="true">
            <div><span>You dragged in: </span>
                <span ng-repeat="name in items track by $index">
                    <span ng-show="$index != 0">,</span>
                    {{name}}
                </span>
            </div>
        </section>
    </div>
    
     See the JSON: <pre>{{items|json}}</pre>
</div>
Charan Ghate
  • 1,384
  • 15
  • 32
3

I've created a wrapper around jQueryUI draggable/droppable a long ago. Might be helpful for you.

Demo: http://codef0rmer.github.com/angular-dragdrop/#/

Source: https://github.com/codef0rmer/angular-dragdrop

codef0rmer
  • 10,284
  • 9
  • 53
  • 76
  • Yes, i searched in google and yoy were the 3 first google responses, but it wasn't exactly what i was looking for.However i have your [page](http://jasonturim.wordpress.com/2013/09/01/angularjs-drag-and-drop/) in favs because i saw it usefull to learn how to use AngularJS and jQuery together, it seems like you give very usefull information about how to create directives. – Ruben Marrero Feb 25 '14 at 23:25