$ Event automatisch mit ng-click übergeben?

69

Ich weiß, dass ich Zugriff auf das Klickereignis erhalten kann, ng-clickwenn ich das $eventObjekt wie folgt übergebe:

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

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

Es ist ein bisschen ärgerlich, $eventjedes Mal explizit passieren zu müssen . Ist es möglich, es so einzustellen ng-click, dass es standardmäßig an die Funktion übergeben wird?

Elise
quelle
10
Ich weiß, dass Code nur zur Demonstration dient, aber undefinedsollte "undefined", sonst wird der Ausdruck immer als falsch ausgewertet, da er typeofeine Zeichenfolge zurückgibt.
Fabrício Matté
1
Ich frage mich, warum Sie $eventsowieso brauchen .
Ein besserer Oliver
6
@zeroflagL Ereignisobjekt wird normalerweise verwendet, um das Sprudeln / die Ausbreitung zu stoppen.
Stewie
3
@Stewie myFunctionist Teil eines Controllers. Ein Controller sollte sich nicht um die Benutzeroberfläche kümmern. Darüber hinaus hat eine einfache Schaltfläche keine Standardaktion. Und Winkel verhindert sowieso viele Standardaktionen. Während Sie Recht haben, ist es natürlich schwer, sich einen guten Anwendungsfall vorzustellen.
ein besserer Oliver
1
@zeroflagL Ich habe eine Direktive, contextMenudie verschiedene Funktionen für den Bereich (Öffnen, Schließen, Umschalten) bereitstellt, die mit dem Namen eines bestimmten aufgerufen werden contextMenu, z ng-click="account_menu.toggle()". Das Menü selbst befindet sich in einem anderen Element, z <div context-menu="account_menu"></div>". Um das Menü auf der Seite direkt unter dem aufgerufenen Triggerelement korrekt zu positionieren toggle(), möchte ich auf ng-clickdas $event.targetElement zugreifen , damit ich seine Koordinaten abrufen kann. Lassen Sie mich wissen, ob es einen einfacheren Weg gibt :)
Elise

Antworten:

64

Werfen Sie einen Blick auf die ng-clickQuelle der Richtlinie:

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

Es zeigt , wie das eventObjekt wird weitergegeben an den ng-clickAusdruck, indem $eventals Name des Parameters. Dies erfolgt durch den $ parse-Dienst, der nicht zulässt, dass die Parameter in den Zielbereich übergehen. Dies bedeutet, dass die Antwort Nein lautet . Sie können $eventnur über den Rückrufparameter auf das Objekt zugreifen .

Stewie
quelle
41

Fügen Sie ein $eventzu dem ng-click, zum Beispiel:

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

Dann jQuery.Eventwurde das an den Rückruf übergeben:

Geben Sie hier die Bildbeschreibung ein

Jeff Tian
quelle
18
... außer dass dies genau das ist, was das OP NICHT zu tun versucht, es sei denn, ich bin verrückt. Der gesamte Zweck dieses Beitrags besteht darin, auf das $ -Ereignis zuzugreifen, ohne es explizit zu übergeben. Dies scheint genau das zu sein, was Sie hier tun.
Dudewad
3
Ich (auf der anderen Seite) kann damit leben
svarog
7
Endete hier nach einer Google-Suche nach dem Bestehen von $ event. Ähnlich wie bei anderen Upvotern wurde die ursprüngliche Frage nicht gelesen: - |
JenonD
11

Wie andere sagten, können Sie nicht genau das tun, wonach Sie fragen. Das heißt, alle Werkzeuge, die für das Winkelgerüst verfügbar sind, stehen Ihnen tatsächlich auch zur Verfügung! Das bedeutet, dass Sie Ihre eigenen Elemente schreiben und diese Funktion selbst bereitstellen können. Ich habe eines davon als Beispiel geschrieben, das Sie im folgenden Abschnitt sehen können ( http://plnkr.co/edit/Qrz9zFjc7Ud6KQoNMEI1 ).

Die wichtigsten Teile davon sind, dass ich ein "anklickbares" Element definiere (tun Sie dies nicht, wenn Sie ältere IE-Unterstützung benötigen). In Code, der aussieht wie:

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

Dann habe ich eine Anweisung definiert, um dieses anklickbare Element in das zu verwandeln, was ich möchte (etwas, das mein Klickereignis automatisch einrichtet):

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

Endlich in meinem Controller habe ich das Klickereignis bereit zu gehen:

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

Nun ist anzumerken, dass dies den Namen der Methode codiert, die das Klickereignis behandelt. Wenn Sie dies beseitigen möchten, sollten Sie in der Lage sein, der Direktive den Namen Ihres Klick-Handlers und "tada" zu geben - Sie haben ein Element (oder Attribut), das Sie verwenden können, und müssen "$ event" nie wieder einfügen.

Hoffentlich hilft das!

zog_w
quelle
1
Sie müssen dieses handleClick-Ereignis zu etwas machen, das übergeben werden kann, Mann :)
vbullinger
2

Ich würde dies nicht empfehlen, aber Sie können die ngClickAnweisung überschreiben, um das zu tun, wonach Sie suchen. Das heißt nicht, du solltest.

Mit Blick auf die ursprüngliche Implementierung:

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

Wir können dies tun, um es zu überschreiben:

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

Dann würden Sie Ihre Funktionen wie folgt übergeben:

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

im Gegensatz zu:

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

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

Wie gesagt, ich würde dies nicht empfehlen, aber es ist ein Proof of Concept, der Ihnen zeigt, dass Sie das eingebaute Winkelverhalten tatsächlich überschreiben / erweitern / erweitern können, um es Ihren Anforderungen anzupassen. Ohne all das tief in die ursprüngliche Implementierung eintauchen zu müssen.

Gehen Sie bitte vorsichtig damit um, wenn Sie sich für diesen Weg entscheiden (es macht jedoch viel Spaß).

Kasper Lewau
quelle