georoot
georoot

Reputation: 3617

Implement html5 drag drop in angularjs?

Here is the view

.container(ng-controller="activityCtrl")
  h3 Edit your plan
  .row
    .one-half.column
      div(draggable="true" ondragstart="onDrag()") I am draggable

And i have defined a function inside controller like

$scope.onDrag = (evt)=>{
  console.log(evt);
  ev.dataTransfer.setData("text", ev.target.id);
}

The error that i am getting is Reference error onDrag not defined. I am guessing that it is somewhat because i need to reference the function defined in $scope in ondragstart. How can i do the same ?

Upvotes: 0

Views: 8449

Answers (2)

Gangadhar Jannu
Gangadhar Jannu

Reputation: 4414

You are getting the error Reference error onDrag not defined because you're referencing a function in HTML5 event which is defined in Angular's scope.

If you really want to access $scope.onDrag function in ondragstart event, change your html like below:

div(draggable="true" ondragstart="angular.element(this).scope().onDrag()") I am draggable

Ideally angular.element(this).scope() would be used for debugging purpose so I would prefer to write a directive for drag and drop.


Below is the HTML5 drag and drop implementation in AngularJS.
I've replicated the same behavior as shown in w3schools.

Since you are manipulating DOM you should use directives in AngularJS.

I've implemented two directives

  • drag-me for drag
  • drop-me-on for drop.

You could also use single directive for both, however I prefer separation of concerns.

HTML:

<div id="div1" drop-on-me>
  <img src="https://www.w3schools.com/html/img_w3slogo.gif" drag-me  id="drag1" width="88" height="31">
</div>

<div id="div2" drop-on-me></div>

JS

angular
  .module('myApp', []);

angular
  .module('myApp')
  .directive('dragMe', dragMe)
  .directive('dropOnMe', dropOnMe);

dragMe.$inject = [];

function dragMe() {
  var DDO = {
    restrict: 'A',
    link: function(scope, element, attrs) {
      element.prop('draggable', true);
      element.on('dragstart', function(event) {
        event.dataTransfer.setData('text', event.target.id)
      });
    }
  };
  return DDO;
}
dropOnMe.$inject = [];
function dropOnMe() {
  var DDO = {
    restrict: 'A',
    link: function(scope, element, attrs) {
      element.on('dragover', function(event) {
        event.preventDefault();
      });
      element.on('drop', function(event) {
        event.preventDefault();
        var data = event.dataTransfer.getData("text");
        event.target.appendChild(document.getElementById(data));
      });
    }
  };
  return DDO;
}

DEMO

Have a look at my fiddle

Upvotes: 11

rodrigoff
rodrigoff

Reputation: 341

OnDragStart is not something from the angular context, so you can't use functions defined in $scope or in your controller.

You could use some third party libraries like angular-dragdrop or ui-sortable or roll your own (see How to Create simple drag and Drop in angularjs for more details).

Upvotes: 0

Related Questions