2013-07-23 17 views
7

Ecco evento è una direttiva in cui sto cercando di disabilitare un collegamento sulla base di un valore del modello:Disattivazione ngClick manipolazione in una direttiva personalizzato

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

voglio essere in grado di disabilitare tutte le azioni di collegamento, a prescindere se usano solo hrefs o azioni ngClick. Gli href funzionano bene a causa della chiamata preventDefault, ma non riesco a capire come scavare nel ngClick e impedirgli di sparare. Il bind che sto facendo sull'evento click non funziona perché sembra che ngClick stia legando il proprio gestore che non ho controllo. C'è qualcosa che posso fare?

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

risposta

8

Usa event.stopImmediatePropagation.

Da MDN:

Se più ascoltatori sono attaccati allo stesso elemento per lo stesso tipo caso, essi sono chiamati in ordine in cui sono stati aggiunti. Se durante una chiamata di questo tipo, viene chiamato event.stopImmediatePropagation(), non verrà chiamato nessun altro ascoltatori rimanenti.

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

    return true; 
}); 
... 

WORKING FIDDLE

+1

stopImmediatePropagation funziona bene fino a v1.0.8, da v1.2.0 non lo fa. testato su un violino correlato. –

4

si potrebbe fare semplicemente cambiare il tuo ng clic per disableIt || tellAboutIt() e che funzionerà come-è. ad esempio

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

codice completo:

HTML (ho rimosso il 'disabile' attributi perché sono inutili in quanto non funzionano sul tag di ancoraggio):

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

angolare (ho fatto la vostra direttiva più compatto):

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/


In alternativa, si potrebbe verificare $scope.disableIt è falso prima di eseguire il codice all'interno tellAboutIt(). per esempio:

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

Probabilmente prenderei una virata leggermente diversa. Invece di cercare di farti entrare in ng-click usando un'altra direttiva. Scriverò semplicemente la mia versione di ng-clic e la userò invece che potrebbe essere attivata/disattivata usando un attributo separato. Se lo facessi, il codice che hai scritto sopra non avrebbe bisogno di cambiare molto per farlo, e potresti semplicemente usare quella direttiva al posto di 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'); 
       } 
      }); 
     } 
    }; 
}); 

Poi, per usarlo:

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