web-dev-qa-db-fra.com

Passer automatiquement $ event avec ng-click?

Je sais que je peux accéder à l'événement click à partir de ng-click si je transmets l'objet $event comme suit:

<button ng-click="myFunction($event)">Give me the $event</button>

<script>
  function myFunction (event) {
    typeof event !== "undefined" // true
  }
</script>

C'est un peu gênant de devoir passer $event explicitement à chaque fois. Est-il possible de définir ng-click pour qu'il le transmette à la fonction par défaut?

67
Elise

Jetez un coup d’œil à la source ng-click de la directive:

...
compile: function($element, attr) {
  var fn = $parse(attr[directiveName]);
  return function(scope, element, attr) {
    element.on(lowercase(name), function(event) {
      scope.$apply(function() {
        fn(scope, {$event:event});
      });
    });
  };
}

Cela montre comment l'objet event est --- transmis à l'expression ng-click, en utilisant $event comme nom du paramètre. Ceci est fait par le service $ parse, ce qui ne permet pas aux paramètres de bleed dans la portée de la cible, ce qui signifie la réponse est non , vous ne pouvez pas accéder à l'objet $event autrement que par le biais du paramètre callback.

63
Stewie

Ajoutez un $event au ng-click, par exemple:

<button type="button" ng-click="saveOffer($event)" accesskey="S"></button>

Ensuite, le jQuery.Event a été transmis au rappel:

enter image description here

36
Jeff Tian

Comme d'autres l'ont dit, vous ne pouvez pas réellement faire ce que vous demandez. Cela dit, tous les outils disponibles dans le cadre angular sont également disponibles! Cela signifie que vous pouvez réellement écrire vos propres éléments et fournir vous-même cette fonctionnalité. J'ai écrit l'un de ces exemples à titre d'exemple, que vous pouvez voir à l'adresse suivante: plunkr ( http://plnkr.co/edit/Qrz9zFjc7Ud6KQoNMEI1 ).

Les éléments clés de ceci sont que je définis un élément "cliquable" (ne le faites pas si vous avez besoin d'une ancienne version de support IE). Dans le code qui ressemble à:

<clickable>
  <h1>Hello World!</h1>
</clickable>

Ensuite, j'ai défini une directive pour prendre cet élément cliquable et le transformer en ce que je veux (quelque chose qui configure automatiquement mon événement click):

app.directive('clickable', function() {
    return {
        transclude: true,
        restrict: 'E',
        template: '<div ng-transclude ng-click="handleClick($event)"></div>'
    };
});

Enfin, dans mon contrôleur, l’événement click est prêt:

$scope.handleClick = function($event) {
    var i = 0;
};

Maintenant, il est intéressant de préciser que ce code code le nom de la méthode qui gère l’événement click. Si vous voulez éliminer cela, vous devriez pouvoir fournir à la directive le nom de votre gestionnaire de clics et "tada" - vous avez un élément (ou un attribut) que vous pouvez utiliser et que vous ne devez plus jamais injecter "$ event".

J'espère que ça t'as aidé!

11
drew_w

Je ne recommanderais pas cela, mais vous pouvez remplacer la directive ngClick pour faire ce que vous recherchez. Cela ne veut pas dire, vous devriez.

Avec la mise en œuvre initiale en tête:

compile: function($element, attr) {
  var fn = $parse(attr[directiveName]);
  return function(scope, element, attr) {
    element.on(lowercase(name), function(event) {
      scope.$apply(function() {
        fn(scope, {$event:event});
      });
    });
  };
}

Nous pouvons faire cela pour le remplacer:

// Go into your config block and inject $provide.
app.config(function ($provide) {

  // Decorate the ngClick directive.
  $provide.decorator('ngClickDirective', function ($delegate) {

    // Grab the actual directive from the returned $delegate array.
    var directive = $delegate[0];

    // Stow away the original compile function of the ngClick directive.
    var origCompile = directive.compile;

    // Overwrite the original compile function.
    directive.compile = function (el, attrs) {

      // Apply the original compile function. 
      origCompile.apply(this, arguments);

      // Return a new link function with our custom behaviour.
      return function (scope, el, attrs) {

        // Get the name of the passed in function. 
        var fn = attrs.ngClick;

        el.on('click', function (event) {
          scope.$apply(function () {

            // If no property on scope matches the passed in fn, return. 
            if (!scope[fn]) {
              return;
            }

            // Throw an error if we misused the new ngClick directive.
            if (typeof scope[fn] !== 'function') {
              throw new Error('Property ' + fn + ' is not a function on ' + scope);
            }

            // Call the passed in function with the event.
            scope[fn].call(null, event);

          });
        });          
      };
    };    

    return $delegate;
  });
});

Ensuite, vous passeriez dans vos fonctions comme ceci:

<div ng-click="func"></div>

par opposition à:

<div ng-click="func()"></div>

jsBin : http://jsbin.com/piwafeke/3/edit

Comme je le disais, je ne recommanderais pas mais c'est une preuve de concept qui vous montre que, oui, vous pouvez en fait écraser/étendre/augmenter la comportement intégré angular pour répondre à vos besoins. Sans avoir à plonger tout cela dans la mise en œuvre initiale.

S'il vous plaît, utilisez-le avec précaution, si vous décidiez de vous engager dans cette voie (c'est quand même très amusant).

2
Kasper Lewau