javascriptangularjsangularjs-ng-touch

How to disable ngTouch conditionally and fallback to ng-click


How can I use ngTouch but selectively disable it for some elements? That is, for certain elements I'd like to use the original ngClick directive instead of the one that ngTouch provides. Something like this:

 <button ng-click-original="myClickFn()">click me</button>

Solution

  • Issue is that once you include ngTouch module in the dependency its version of ngClick ngTouch.directive('ngClick' will override the original ngClickDirective of angular core. So all the clicks will be handled by ngTouch's version of ng-click so you would need to decorate the ngCLick in your module to handle your scenario. I can think of couple of approaches here:-

    Approach 1 - Create your own directive

    How about creating an ng-click-orig probably don't prefix it with ng since it is a custom directive.

    .directive('ngClickOrig', ['$parse', function($parse) {
          return {
            compile: function($element, attr) {
              var fn = $parse(attr["ngClickOrig"]);
              return function handler(scope, element) {
                element.on('click', function(event) {
                  scope.$apply(function() {
                    fn(scope, {$event:event});
                  });
                });
              };
            }
         };
     }]);
    

    Demo


    Approach 2:- With decorator for ng-Click directive

    Another way create a decorator on ngClickDirective, look for specific attribute say notouch and perform regular click or use the original one provided by ngTouch.

    .config(function($provide){
       //Create a decoration for ngClickDirective   
       $provide.decorator('ngClickDirective', ['$delegate','$parse', function($delegate, $parse) {
            //Get the original compile function by ngTouch
            var origValue = $delegate[0].compile();
            //Get set the compiler
            $delegate[0].compile = compiler;
            //return augmented ngClick
            return $delegate;
    
           /*Compiler Implementation*/
           function compiler(elm, attr){
              //Look for "notouch" attribute, if present return regular click event, 
              //no touch simulation
              if(angular.isDefined(attr.notouch)){
                var fn = $parse(attr["ngClick"]);
                return function handler(scope, element) {
                  element.on('click', function(event) {
                    scope.$apply(function() {
                      fn(scope, {$event:event});
                    });
                  });
                }
              }
              //return original ngCLick implementation by ngTouch
              return origValue;
             }
       }]);
    });
    

    Just as a note decorator will not run until the directive is used for the first time and it will run only once.

    Example Usage:-

       <button ng-click="myClickFn()" notouch>click me</button> <-- see notouch attribute -->
       <button ng-click="myClickFnTouch()">click me</button>
    

    Demo-Decorator