38

How do I register my own event listeners in an AngularJS app?

To be specific, I am trying to register Drag and Drop (DND) listeners so that when something is dragged and dropped in a new location of my view, AngularJS recalculates the business logic and updates the model and then the view.

3 Answers 3

47

Adding an event listener would be done in the linking method of a directive. Below I've written some examples of basic directives. HOWEVER, if you wanted to use jquery-ui's .draggable() and .droppable(), what you can do is know that the elem param in the link function of each directive below is actually a jQuery object. So you could call elem.draggable() and do what you're going to do there.

Here's an example of binding dragstart in Angular with a directive:

app.directive('draggableThing', function(){ 
   return {
      restrict: 'A', //attribute only
      link: function(scope, elem, attr, ctrl) {
         elem.bind('dragstart', function(e) {
            //do something here.
         });
      }
   };
});

Here's how you'd use that.

<div draggable-thing>This is draggable.</div>

An example of binding drop to a div or something with Angular.

app.directive('droppableArea', function() {
   return {
       restrict: 'A',
       link: function(scope, elem, attr, ctrl) {
            elem.bind('drop', function(e) {
                /* do something here */
            });
       }
   };
});

Here's how you'd use that.

<div droppable-area>Drop stuff here</div>

I hope that helps.

Sign up to request clarification or add additional context in comments.

5 Comments

I really appreciate you taking the time to share your experience with AngularJS. Since I am so knew to AngularJS, I prefer to not mudding the water at this point with other 3rd party libraries right now; so I am definitely looking for an all AngularJS solution. So do I understand right, a directive is basically an event? Or it can only register an event? I will play around with these directives some more and report back what I've learned. Thanks!
A directive is the wiring for angular. It does the work of tying in elements and attributes from your markup to your JS code. So, controllers are just logic and rules, templates are your UI, and directives (along with $scope) are what tie them together.
You can and should use a directive whenever you need to do something like: 1. a reusable control. 2. DOM manipulation. 3. event binding. etc.
@TontePouncil maybe should award the answer? Seems like it worked out.
voted up for the use of directive - this was the answer that saved me from JQuery and low level DOM manipulation madness
8

Hiding event handling and dom manipulation in a directive is pretty much the the angularjs way. Calling scope.$apply when an event fires tells angular to update the view.

You might consider using jquery-ui like in this sample (see angular wiki of examples I work with the angular-ui group and there is a simple event wrapper you might find useful.

4 Comments

Thank you for your response. I am very new to angularjs and I am not sure that I am using it correctly. At any rate, I looked at your jquery-ui sample app and I wasn't too sure how jquery-ui came into the picture other than the following directive: jqui-drag-start, jqui-drag-end, jqui-drop-accept, and jqui-drop-commit. Is that correct? Is that true? I went out to the JQuery UI site but didn't see these directive out there. So where did they come from? It seems like directive are events and whatever we set them equal to are the event handlers. Is that correct?
It also looks like you created two directives (jqui-drag-start and jqui-drag-end)?
Basically the author of the directive (not me) chose to wrap the jquery ui draggable and droppable interactions. In this case, he is really in tune with how the jqueryui plugin works. Directives can be very simple or very complex. Directives can be a number of things, early on they were broken into widgets and directives. Now they are just directives.
$scope.$apply() helped me a lot!
3

Nice solution by Ben but keep in mind you will need to access originalEvent and original element. According to Mozilla documentation two conditions must meet https://developer.mozilla.org/en-US/docs/DragDrop/Drag_Operations

  1. draggable is true
  2. Listener for dragstart

So directive might look something like this

app.directive('draggableThing', function () {
    return function(scope, element, attr) {
        var pureJsElement = element[0];
        pureJsElement.draggable = true;
        element.bind('dragstart', function(event) {
            event.originalEvent.dataTransfer.setData('text/plain', 
                              'This text may be dragged');
        //do something here.
        });
    }
});

A good step by step example is available here http://blog.parkji.co.uk/2013/08/11/native-drag-and-drop-in-angularjs.html

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.