103

我想创建一个链接到属性的指令。该属性指定应在作用域上调用的函数。但我也想将参数传递给在链接函数内部确定的函数。

<div my-method='theMethodToBeCalled'></div>

在链接函数中,我绑定到一个 jQuery 事件,该事件传递了我需要传递给函数的参数:

app.directive("myMethod",function($parse) {
  restrict:'A',
  link:function(scope,element,attrs) {
     var expressionHandler = $parse(attrs.myMethod);
     $(element).on('theEvent',function( e, rowid ) {
        id = // some function called to determine id based on rowid
        scope.$apply(function() {expressionHandler(id);});
     }
  }
}

app.controller("myController",function($scope) {
   $scope.theMethodToBeCalled = function(id) { alert(id); };
}

不传递 id 我可以让它工作,但是一旦我尝试传递一个参数,就不再调用该函数

4

7 回答 7

98

Marko 的解决方案效果很好

与推荐的 Angular 方式(如 treeface 的 plunkr 所示)相比,使用不需要定义 expressionHandler 的回调表达式。在 marko 的示例更改中:

在模板中

<div my-method="theMethodToBeCalled(myParam)"></div>

在指令链接函数中

$(element).click(function( e, rowid ) {
  scope.method({myParam: id});
});

与 marko 的解决方案相比,这确实有一个缺点 - 在第一次加载时,将使用 myParam === undefined 调用 MethodToBeCalled 函数。

可以在@treeface Plunker找到一个工作示例

于 2013-11-21T18:19:16.590 回答
96

只是为其他答案添加一些信息 -&如果您需要隔离范围,使用是一种好方法。

marko 解决方案的主要缺点是它迫使您在一个元素上创建一个孤立的范围,但您只能在一个元素上拥有其中一个(否则您会遇到角度错误:Multiple directives [directive1,directive2] ask对于隔离范围

这意味着您:

  • 不能在一个元素上使用它帽子本身有一个孤立的范围
  • 不能在同一元素上使用此解决方案的两个指令

由于原始问题在两种情况下都使用了指令,restrict:'A'因此在更大的应用程序中可能经常出现,并且在这里使用隔离范围不是一个好习惯,也是不必要的。事实上,rekna 在这种情况下有一个很好的直觉,并且几乎让它工作,他做错的唯一一件事就是错误地调用了$parsed函数(看看它在这里返回什么:https ://docs.angularjs.org/api/ ng/服务/$ 解析)。

TL;博士; 固定问题代码

<div my-method='theMethodToBeCalled(id)'></div>

和代码

app.directive("myMethod",function($parse) {
  restrict:'A',
  link:function(scope,element,attrs) {
     // here you can parse any attribute (so this could as well be,
     // myDirectiveCallback or multiple ones if you need them )
     var expressionHandler = $parse(attrs.myMethod);
     $(element).on('theEvent',function( e, rowid ) {
        calculatedId = // some function called to determine id based on rowid

        // HERE: call the parsed function correctly (with scope AND params object)
        expressionHandler(scope, {id:calculatedId});
     }
  }
}

app.controller("myController",function($scope) {
   $scope.theMethodToBeCalled = function(id) { alert(id); };
}
于 2014-06-14T22:49:31.920 回答
88

不知道你想做什么......但仍然是一个可能的解决方案。

在本地范围内创建具有“&”属性的范围。它“提供了一种在父范围的上下文中执行表达式的方法”(有关详细信息,请参阅指令文档)。

我还注意到您使用了速记链接功能并在其中插入了对象属性。你不能那样做。只返回指令定义对象更清楚(恕我直言)。请参阅下面的代码。

这是一个代码示例和一个小提琴

<div ng-app="myApp">
<div ng-controller="myController">
    <div my-method='theMethodToBeCalled'>Click me</div>
</div>
</div>

<script>

   var app = angular.module('myApp',[]);

   app.directive("myMethod",function($parse) {
       var directiveDefinitionObject = {
         restrict: 'A',
         scope: { method:'&myMethod' },
         link: function(scope,element,attrs) {
            var expressionHandler = scope.method();
            var id = "123";

            $(element).click(function( e, rowid ) {
               expressionHandler(id);
            });
         }
       };
       return directiveDefinitionObject;
   });

   app.controller("myController",function($scope) {
      $scope.theMethodToBeCalled = function(id) { 
          alert(id); 
      };
   });

</script>
于 2013-07-10T12:20:07.767 回答
6

attrName: "&"您可以创建一个指令,通过使用引用外部范围内的表达式来执行带有参数的函数调用。

我们想用以下指令替换ng-click指令ng-click-x

<button ng-click-x="add(a,b)">Add</button>

如果我们有这个范围:

$scope.a = 2;
$scope.b = 2;

$scope.add = function (a, b) {
  $scope.result = parseFloat(a) + parseFloat(b);
}

我们可以这样写我们的指令:

angular.module("ng-click-x", [])

.directive('ngClickX', [function () {

  return {

    scope: {

      // Reference the outer scope
      fn: "&ngClickX",

    },

    restrict: "A",

    link: function(scope, elem) {

      function callFn () {
        scope.$apply(scope.fn());
      }

      elem[0].addEventListener('click', callFn);
    }
  };
}]);

这是一个现场演示: http ://plnkr.co/edit/4QOGLD?p=info

于 2015-11-05T19:11:32.540 回答
2

这对我有用。

使用指令的 HTML

 <tr orderitemdirective remove="vm.removeOrderItem(orderItem)" order-item="orderitem"></tr>

指令的html:orderitem.directive.html

<md-button type="submit" ng-click="remove({orderItem:orderItem})">
       (...)
</md-button>

指令范围:

scope: {
    orderItem: '=',
    remove: "&",
于 2016-09-05T23:57:13.063 回答
0

我的解决方案:

  1. 在聚合物上引发事件(例如complete
  2. 定义将事件链接到控制功能的指令

指示

/*global define */
define(['angular', './my-module'], function(angular, directives) {
    'use strict';
    directives.directive('polimerBinding', ['$compile', function($compile) {

            return {
                 restrict: 'A',
                scope: { 
                    method:'&polimerBinding'
                },
                link : function(scope, element, attrs) {
                    var el = element[0];
                    var expressionHandler = scope.method();
                    var siemEvent = attrs['polimerEvent'];
                    if (!siemEvent) {
                        siemEvent = 'complete';
                    }
                    el.addEventListener(siemEvent, function (e, options) {
                        expressionHandler(e.detail);
                    })
                }
            };
        }]);
});

聚合物组分

<dom-module id="search">

<template>
<h3>Search</h3>
<div class="input-group">

    <textarea placeholder="search by expression (eg. temperature>100)"
        rows="10" cols="100" value="{{text::input}}"></textarea>
    <p>
        <button id="button" class="btn input-group__addon">Search</button>
    </p>
</div>
</template>

 <script>
  Polymer({
    is: 'search',
            properties: {
      text: {
        type: String,
        notify: true
      },

    },
    regularSearch: function(e) {
      console.log(this.range);
      this.fire('complete', {'text': this.text});
    },
    listeners: {
        'button.click': 'regularSearch',
    }
  });
</script>

</dom-module>

 <search id="search" polimer-binding="searchData"
 siem-event="complete" range="{{range}}"></siem-search>

searchData是控制函数

$scope.searchData = function(searchObject) {
                    alert('searchData '+ searchObject.text + ' ' + searchObject.range);

}
于 2016-03-01T15:35:23.967 回答
-2

这应该有效。

<div my-method='theMethodToBeCalled'></div>

app.directive("myMethod",function($parse) {
  restrict:'A',
  scope: {theMethodToBeCalled: "="}
  link:function(scope,element,attrs) {
     $(element).on('theEvent',function( e, rowid ) {
        id = // some function called to determine id based on rowid
        scope.theMethodToBeCalled(id);
     }
  }
}

app.controller("myController",function($scope) {
   $scope.theMethodToBeCalled = function(id) { alert(id); };
}
于 2015-10-22T12:07:48.447 回答