it-swarm.com.ru

Автоматически передавать $ событие с помощью ng-click?

Я знаю, что могу получить доступ к событию click из ng-click, если передам объект $event следующим образом:

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

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

Немного раздражает необходимость каждый раз явно передавать $event. Можно ли установить ng-click, чтобы как-то передать его функции по умолчанию?

67
Elise

Посмотрите на источник директивы ng-click:

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

показывает как объект event передается в выражение ng-click, используя $event в качестве имени параметра. Это делается службой $ parse, которая не позволяет параметрам попадать в целевую область, что означает ответ нет , вы не можете получить доступ к объекту $event любым другим способом, кроме как через параметр обратного вызова.

63
Stewie

Добавьте $event к ng-click, например:

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

Затем jQuery.Event был передан обратному вызову:

enter image description here

35
Jeff Tian

Как говорили другие, вы не можете строго выполнять то, о чем просите. Тем не менее, все инструменты, доступные для структуры angular, на самом деле доступны и вам! Это означает, что вы можете написать свои собственные элементы и предоставить эту функцию самостоятельно. Я написал один из них в качестве примера, который вы можете увидеть на следующем plunkr ( http://plnkr.co/edit/Qrz9zFjc7Ud6KQoNMEI1 ).

Ключевыми частями этого является то, что я определяю "кликабельный" элемент (не делайте этого, если вам нужна более старая поддержка IE). В коде это выглядит так:

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

Затем я определил директиву, чтобы взять этот кликабельный элемент и превратить его в то, что я хочу (то, что автоматически настраивает мое событие click):

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

Наконец, в моем контроллере у меня есть готовое событие click:

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

Теперь стоит указать, что этот код жестко задает имя метода, который обрабатывает событие click. Если вы хотите устранить это, вы сможете указать директиву с именем вашего обработчика щелчков и "tada" - у вас есть элемент (или атрибут), который вы можете использовать, и вам никогда не придется вводить "$ event" снова.

Надеюсь, это поможет!

11
drew_w

Я бы не рекомендовал делать это, но вы можете переопределить директиву ngClick, чтобы сделать то, что вы ищете. Это не говорит, вы должны.

С учетом оригинальной реализации:

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

Мы можем сделать это, чтобы переопределить это:

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

Тогда вы передадите свои функции следующим образом:

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

в отличие от:

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

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

Как я уже сказал, я бы не рекомендовал делать это, но это доказательство концепции, показывающей, что да - вы можете перезаписать/расширить/дополнить встроенное angular поведение в соответствии с вашими потребностями. Без необходимости копать все это глубоко в оригинальной реализации.

Пожалуйста, используйте его с осторожностью, если вы решили пойти по этому пути (хотя это очень весело).

2
Kasper Lewau