Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling ng-click and ng-dblclick on the same element with AngularJS

I was looking for both single and double-click event handling with AngularJS, since AngularJS always fires only the ng-click event even if there is ng-dblclick directive set for our element.

Here is some working code for those who seek solution:

JS:

function MyController($scope) {      var waitingForSecondClick = false;     $scope.singleClickAction = function() {          executingDoubleClick = false;         if (waitingForSecondClick) {             waitingForSecondClick = false;             executingDoubleClick = true;             return $scope.doubleClickAction();         }         waitingForSecondClick = true;          setTimeout(function() {             waitingForSecondClick = false;             return singleClickOnlyAction();         }, 250); // delay          /*          * Code executed with single AND double-click goes here.          * ...          */          var singleClickOnlyAction = function() {             if (executingDoubleClick) return;              /*              * Code executed ONLY with single-click goes here.              * ...              */          }      }      $scope.doubleClickAction = function() {          /*          * Code executed ONLY with double-click goes here.          * ...          */      };  } 

HTML:

<div ng-controller="MyController">     <a href="#" ng-click="singleClickAction()">CLICK</a> </div> 

So my question is (since I'm an AngularJS newbie): could somebody more experianced write some nice directive for handling those both events?

In my opinion the perfect way would be to change the behaviour of ng-click, ng-dblclick and add some "ng-sglclick" directive for handling single-click-only code. Don't know if it is even possible, but I'd find it very useful for everyone.

Feel free to share your opinions!

like image 552
stealz Avatar asked Dec 07 '13 17:12

stealz


People also ask

Can we use NG-click and Onclick together?

For a single btn, it's ok to use ng-click or onclick in the ng-app . There is no difference between the two functions. For effective team work, you,d better to have an account with each other. In Angular apps, ng-click is recommended.

Can we call two functions on Ng-click?

When an HTML is clicked, the ng-click directive tells the AngularJS script what to do. In this article, we will learn how to get many/multiple functions to the ng-click directive passed, in just one click. The key is to add a semi-colon (;) or a comma (,). All the functions must be separated by a (;) or a (, ).

What is Ng Dblclick in AngularJS?

The ng-dblclick directive tells AngularJS what to do when an HTML element is double-clicked. The ng-dblclick directive from AngularJS will not override the element's original ondblclick event, both are executed.

What is the difference between Ng-click and Onclick?

Another significant difference between ng-click and onclick is the execution context. Code inside an onclick attribute executes against the global window object, while an expression inside of ng-click executes against a specific scope object, typically the scope object representing the model for the current controller.


2 Answers

You could just write your own. I took a look at how angular handled click and modified it with code I found here: Jquery bind double click and single click separately

<div sglclick="singleClick()" ng-dblClick="doubleClick()" style="height:200px;width:200px;background-color:black">   mainMod.controller('AppCntrl', ['$scope', function ($scope) {     $scope.singleClick = function() {       alert('Single Click');     }     $scope.doubleClick = function() {       alert('Double Click');     } }])   mainMod.directive('sglclick', ['$parse', function($parse) {     return {         restrict: 'A',         link: function(scope, element, attr) {           var fn = $parse(attr['sglclick']);           var delay = 300, clicks = 0, timer = null;           element.on('click', function (event) {             clicks++;  //count clicks             if(clicks === 1) {               timer = setTimeout(function() {                 scope.$apply(function () {                     fn(scope, { $event: event });                 });                  clicks = 0;             //after action performed, reset counter               }, delay);               } else {                 clearTimeout(timer);    //prevent single-click action                 clicks = 0;             //after action performed, reset counter               }           });         }     }; }]) 

Here's an example

Plunker

like image 170
Rob Avatar answered Oct 06 '22 11:10

Rob


Greg's answer is definitely closest to the cleanest answer. I'm going to build on his answer to come up with a version where no new code needs to be written, and no new injections need to be used in your controller.

The first thing to question is why timeouts are used to hack around these kinds of problems. Essentially, they're used to make a function skip the rest of the current event loop so that the execution is clean. In angular, however, you are actually interested in how the digest loop works. It's almost the same as your classic event handler, except for some minor differences which make it great for UX. Some tools that you have on hand to mess around with the order of function execution include scope.$eval, scope.$evalAsync,scope.$apply, and scope.$applyAsync.

I believe the $applys will kick off another digest loop, which leaves the $evals. $eval will run whatever code you include immediately with the context of the current $scope and $evalAsync will queue your function to be run at the end of the digest loop. Essentially, $evalAsync is a cleaner version of $timeout with one big difference — the first has context and exists on the scope!

This means that you can, actually, handle ng-click and ng-dblclick on the same element. Note, however, that this will still trigger the single-click function before the double-click function. This should be sufficient:

<div ng-controller="MyController">     <a href="#"        ng-click="$evalAsync(singleClickAction())"        ng-dblclick="doubleClickAction()">        CLICK     </a> </div> 

Here's a jsfiddle with the intended functionality using Angular 1.6.4.

like image 40
stites Avatar answered Oct 06 '22 12:10

stites