angularjs指令在属性中指定的调用函数,并将参数传递给它

rek*_*kna 100 angularjs-directive

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

<div my-method='theMethodToBeCalled'></div>
Run Code Online (Sandbox Code Playgroud)

在链接函数中,我绑定到一个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); };
}
Run Code Online (Sandbox Code Playgroud)

如果没有传递id,我可以使它工作,但是一旦我尝试传递参数,该函数就不再被调用了

joh*_*ans 98

Marko的解决方案效果很好.

与推荐的Angular方式(如treeface的plunkr所示)的对比是使用不需要定义expressionHandler的回调表达式.在marko的例子中改变:

在模板中

<div my-method="theMethodToBeCalled(myParam)"></div>
Run Code Online (Sandbox Code Playgroud)

在指令链接功能

$(element).click(function( e, rowid ) {
  scope.method({myParam: id});
});
Run Code Online (Sandbox Code Playgroud)

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

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

  • 调用"setProduct"2个不同的东西 - 属性和范围函数是非常令人困惑的,这使得很难理解哪一个在哪里. (3认同)

Rob*_*Bak 93

只是为其他答案添加一些信息 - &如果您需要一个独立的范围,使用是一个好方法.

marko解决方案的主要缺点是它会强制你在一个元素上创建一个独立的范围,但你只能在一个元素上有一个(否则你会遇到一个角度错误:多指令[directive1,directive2]问适用于隔离范围)

这意味着你:

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

由于原始问题使用指令,restrict:'A'因此在较大的应用程序中可能经常出现这两种情况,并且在此使用隔离范围不是一种好的做法,也不是必需的.事实上rekna在这种情况下有一个很好的直觉,几乎让它工作,他唯一错误的就是调用$ parsed函数错误(看看它返回的内容:https://docs.angularjs.org/api/ ng/service/$ parse).

TL; DR; 修正了问题代码

<div my-method='theMethodToBeCalled(id)'></div>
Run Code Online (Sandbox Code Playgroud)

和代码

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); };
}
Run Code Online (Sandbox Code Playgroud)

  • +1确实 - 无需隔离范围 - 更清洁! (11认同)

mar*_*rko 87

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

在本地范围内创建一个带有"&" - 属性的范围.它"提供了一种在父作用域的上下文中执行表达式的方法"(有关详细信息,请参阅指令文档).

我还注意到你使用了一个速记链接函数并在那里的对象属性中推了推.你不能这样做.更简单的是(imho)返回指令定义对象.请参阅下面的代码.

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

<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>
Run Code Online (Sandbox Code Playgroud)

  • 这是第二种(可能更有棱角分明的)方式:http://plnkr.co/edit/r9CV9Y1RWRuse4RwFPka?p=preview (3认同)
  • +1因为这个解决方案告诉我我需要调用scope.method(); 首先得到对方法的实际引用. (3认同)
  • 太棒了,这有助于我找到解决问题的方法.值得一提的是,如果您正在进行更深层次的指令,您只需要在顶层执行此操作.考虑一下:http://plnkr.co/edit/s3y67iGL12F2hDER2RNl?p = preview我在哪里通过两个指令传递方法. (2认同)

f1l*_*t3r 6

您可以使用attrName: "&"引用外部作用域中的表达式来创建一个使用params执行函数调用的指令.

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

<button ng-click-x="add(a,b)">Add</button>
Run Code Online (Sandbox Code Playgroud)

如果我们有这个范围:

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

$scope.add = function (a, b) {
  $scope.result = parseFloat(a) + parseFloat(b);
}
Run Code Online (Sandbox Code Playgroud)

我们可以写这样的指令:

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);
    }
  };
}]);
Run Code Online (Sandbox Code Playgroud)

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