2013-07-23 40 views
7

這裏處理是在我試圖基於模型的值來禁用一個鏈接指令:禁用ngClick事件中的自定義指令

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'); 
        } 
       }); 
      } 
     } 
    }; 
}); 

我希望能夠禁用所有鏈接的操作,不管他們是否使用簡單的hrefs或ngClick操作。由於preventDefault調用,Hrefs可以正常工作,但我無法弄清楚如何挖掘ngClick並防止它觸發。我正在做的點擊事件的綁定不起作用,因爲它看起來ngClick綁定了我自己的控制器,我無法控制。有什麼我可以做的嗎?

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

回答

8

使用event.stopImmediatePropagation

MDN

如果幾個監聽器連接到相同的元件爲同一 事件類型,它們被稱爲在它們已被添加順序。如果 在一次這樣的調用期間調用event.stopImmediatePropagation(),則將不會調用其餘的監聽器 。

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

    return true; 
}); 
... 

WORKING FIDDLE

+1

stopImmediatePropagation正常工作達v1.0.8,從V1.2.0沒有。在相關的小提琴上測試。 –

4

你可以做簡單的改變你的NG-點擊disableIt || tellAboutIt(),它會過去一樣工作。例如

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

全碼:

HTML(我已經刪除了 '禁用' 屬性,因爲他們是無用的,因爲他們不錨標籤工作):

<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> 

(我已使您的指令更加緊湊):

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/


或者,你可以檢查$scope.disableIt是運行裏面tellAboutIt()代碼之前假。例如:

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

我可能會略微不同。而不是試圖用自己的指令撬動自己進入ng-click。我只需編寫我自己的ng-click版本並使用它,然後就可以使用單獨的屬性來打開/關閉它。如果你這樣做了,那麼上面編寫的代碼不需要做太多改變就可以做到這一點,你可以使用該指令代替ng-click。

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'); 
       } 
      }); 
     } 
    }; 
}); 

然後使用它:

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