2013-07-23 6 views
7

Hier ist eine Richtlinie, in der ich auf einem Modellwert einen Link basierte zu deaktivieren bin versucht:Deaktivieren ngClick Ereignis in einer benutzerdefinierten Richtlinie Handhabung

app.directive('disableable', function($parse){ 
    return { 
     restrict: 'C', 
     require: '?ngClick', 
     link: function (scope, elem, attrs, ngClick) { 
      if (attrs.disable){ 
       var disable = $parse(attrs.disable); 

       elem.bind('click', function (e) { 
        if (disable(scope)){ 
         e.preventDefault(); 
         return false; 
        } 

        return true; 
       }); 

       scope.$watch(disable, function (val) { 
        if (val){ 
         elem.addClass('disabled'); 
         elem.css('cursor', 'default'); 
        } 
        else { 
         elem.removeClass('disabled'); 
         elem.css('cursor', 'pointer'); 
        } 
       }); 
      } 
     } 
    }; 
}); 

Ich möchte in der Lage sein, alle Links Aktionen zu deaktivieren, und zwar unabhängig ob sie einfache hrefs oder ngClick-Aktionen verwenden. Hrefs funktionieren gut wegen des Aufrufs preventDefault, aber ich kann nicht herausfinden, wie man in ngClick eingräbt und verhindert, dass es ausgelöst wird. Die Bindung, die ich für das click -Ereignis mache, funktioniert nicht, da es so aussieht, als ob ngClick einen eigenen Handler bindet, über den ich keine Kontrolle habe. Kann ich irgendetwas tun?

jsFiddle: http://jsfiddle.net/KQQD2/2/

Antwort

8

Verwenden event.stopImmediatePropagation.

Von MDN:

Wenn mehrere Zuhörer auf das gleiche Element für den gleichen Ereignistyp gebunden sind, werden sie aufgerufen, um in der sie hinzugefügt wurden. Wenn während eines solchen Aufrufs, event.stopImmediatePropagation() aufgerufen wird, werden keine verbleibenden Listener aufgerufen.

... 
elem.bind('click', function (e) { 
    if (disable(scope)){ 
    e.stopImmediatePropagation(); 
    return false; 
    } 

    return true; 
}); 
... 

WORKING FIDDLE

+1

stopImmediatePropagation arbeitet an v1.0.8 fein auf, von v1.2.0 nicht der Fall ist. auf verwandter Geige getestet. –

4

Sie könnten einfach Ihre ändern sich ng Klick auf disableIt || tellAboutIt() und es wird funktionieren, wie sie ist. zB

<a class="disableable" target="_blank" ng-click="disableIt || tellAboutIt()"> 
      ngClick disableable link</a> 

Voll Code:

HTML (ich habe die entfernt 'behindert' Attribute, weil sie nutzlos sind, da sie Anker-Tags nicht auf Arbeit):

<div ng-app="app" ng-controller="appCtrl"> 
    <a class="disableable" target="_blank" ng-click="disableIt || tellAboutIt()"> 
     ngClick disableable link</a> 
    <br/><br/> 
    <a class="disableable" target="_blank" href="http://google.com"> 
     href disableable link</a> 
    <br/><br/> 
    <input type="checkbox" ng-model="disableIt" /> Disable links 
</div> 

Angular (ich gemacht habe Ihre Richtlinie kompaktere):

app.directive('disableable', function($parse){ 
    return { 
     restrict: 'C', 
     link: function (scope, elem, attrs) { 
      scope.$watch('disableIt', function (val) { 
       if (val) { 
        elem.addClass('disabled'); 
        elem.css('cursor', 'default'); 
        elem.bind('click', function(e) { 
         e.preventDefault(); 
        }); 
       } 
       else { 
        elem.removeClass('disabled'); 
        elem.css('cursor', 'pointer'); 
        if (typeof elem.attr('ng-click') === 'undefined') 
         elem.unbind('click'); 
       } 
      }); 
     } 
    }; 
}); 

JSFiddle: http://jsfiddle.net/KQQD2/4/


Alternativ können Sie überprüfen $scope.disableIt den Code in tellAboutIt() vor der Ausführung falsch ist. Beispiel:

$scope.tellAboutIt = function(){ 
    if ($scope.disableIt === false) { 
     $window.alert('ngClick fired. This alert should not show when disabled.'); 
    } 
}; 
0

Ich würde wahrscheinlich eine etwas andere Wende nehmen. Anstatt zu versuchen, mit einer anderen Anweisung in ng-click zu springen. Ich würde einfach meine eigene Version von ng-click schreiben und diese stattdessen verwenden, dann kann sie mit einem separaten Attribut ein- und ausgeschaltet werden. Wenn Sie das getan hätten, müsste sich der Code, den Sie oben geschrieben haben, nicht viel ändern, um dies zu tun, und Sie könnten einfach diese Anweisung anstelle von ng-click verwenden.

app.directive('enabled-click', function() { 
    return { 
     scope: { 
      enabledClick: '&', 
      enabled: '=' 
     }, 
     restrict: 'A', 
     link: function(scope, element, attributes) { 
      element.bind('click', function(event) { 
       if(scope.enabled) { 
        if(element.target) { 
        return true; // external link 
        } else { 
        scope.enabledClick(); 
        return false; 
        } 
       } else { 
        event.preventDefault(); 
        return false; 
       } 
      }); 
      scope.$watch('enabled', function(val) { 
       if(val) { 
        element.removeClass('disabled'); 
       } else { 
        element.addClass('disabled'); 
       } 
      }); 
     } 
    }; 
}); 

Dann, es zu benutzen:

<a href="#something" enabled-click="doSomething()" enabled="!disable">Blah</a> 
Verwandte Themen