将参数传递给范围函数,从ng-repeat内的指令传递

时间:2014-12-30 04:12:46

标签: angularjs angularjs-directive angularjs-ng-repeat

我试图从指令调用函数并传递参数。回调函数正被传递到隔离范围。我有两个问题。首先,当嵌套在ng-repeat中时,这根本不起作用,第二,即使不在ng-repeat中,我也不知道如何将参数传递给回调函数。这是一个显示问题的傻瓜:http://plnkr.co/edit/3FN0o3UE99wsmUpxMe4x?p=preview

请注意,当您单击"这适用于"时,它至少会执行父作用域中的功能,但是当点击其他作用时,它什么也不做(因为它们在内部? -重复)。这是第一个问题。

第二个问题是当你点击"这有效",即使它成功调用了该函数,我也无法弄清楚如何从指令范围传递用户(通知它警告未定义)。

这是一个示例指令(从我的实际应用程序中大大简化):

var app = angular.module('plunker', []);
app.controller("AppCtrl", function($scope) {
  $scope.click = function(user) {
    alert(user)
  }
  $scope.users = [{
    name: 'John',
    id: 1
  }, {
    name: 'anonymous'
  }];
});
app.directive("myDir", function($compile) {
  return {
    scope: {
      user: '=',
      click: '&'
    },
    compile: function(el) {
      el.removeAttr('my-dir');
      el.attr('ng-click', 'click(user)')
      var fn = $compile(el);
      return function(scope, el){
        fn(scope);
      };
    }
  };
});

这是html:

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="angular.js@1.2.x" src="http://code.angularjs.org/1.2.12/angular.js" data-semver="1.2.12"></script>
    <script src="app.js"></script>
  </head>

  <body>
    <div ng-controller="AppCtrl">
        <a my-dir user="{name: 'Works', id: 0}" click="click()">This works</a>
        <a my-dir user="user" click="click()" ng-repeat="user in users"><br>{{user.name}}</a>
    </div>
  </body>

</html>

谢谢!

2 个答案:

答案 0 :(得分:3)

当然,对于这样的事情,编译功能是不需要的。实际上,从1.2开始,编译函数几乎从不需要。我已经看到MIGHT需要编译功能的唯一指令是ng-repeat指令本身,我甚至不相信这是真的。

要记住的一件重要事情是,当一个函数传递给一个指令来被调用时,当在html中指定了该函数时,这就是参数绑定时的情况。所以给出了以下控制器(注意我重命名了被调用的函数更明确)

app.controller("AppCtrl", function($scope) {
  $scope.raiseNotification = function(user) {
    alert(user.name)
  }
....

以及以下指令:

app.directive("myDir", function($compile) {
  return {
    restrict: 'E',
    scope: {
      user: '=',
      click: '&'
    },
    template: '<a ng-click="click()" ><br>{{user.name}}</a>'
  };
});

如果你想调用这个方法,那么下面的HTML就是你想要的

<div ng-repeat="user in users">
  <my-dir user="user" click="raiseNotification(user)" ></my-dir>
</div>

调用click时(请注意,指令模板中的click()没有自己的参数。因为模板中的click()实际上是调用raiseNotification的包装器(用户)即

function click() {
  raiseNotification(user);
}

如果您希望从指令中的某个位置调用click函数并覆盖用户绑定的内容,那么您可以这样做:

click({user:myOtherUser})

这将覆盖&#34;用户&#34;参数绑定到。这是一个非常优秀的案例。

Here's对像素比特代码的调整,其中包含未在指令模板中指定的用户参数的修复程序。

另外,只是为了好玩,here's另一个版本更接近你正在做的事情但使用链接功能。它不像以前给出的代码那样简洁或优雅,但如果你需要对节点上的事件做更具体的事情,可以使用链接功能进行更多控制。

答案 1 :(得分:1)

当您尝试重新编译/重新链接已编译或正在编译的指令时,可能会导致此问题。当你试图重新编译/重新链接一个指令时,这是一个重要的红旗,你正在做一些你不应该做的事情。

而不是与框架作斗争,并让它做一些它不应该做的模糊的事情,尝试在框架内工作,你会发现完成这些任务要容易得多。做。

首先,这是一个有效的demo

提示1:如果您要重新编译指令 - 请不要。这有很多陷阱,比它的价值更麻烦。重新组织您的HTML,这样您就不必:

<div ng-controller="AppCtrl">
    <div ng-init="user = {name: 'Works', id: 0}">
      <my-dir user="user"  click="click(user)"></my-dir>
    </div>

    <div ng-repeat="user in users">
      <my-dir user="user" click="click(user)" ></my-dir>
    </div>
</div>

提示2 :如果您正在使用隔离范围,请在指令中使用模板。模板可以利用隔离范围,并有助于使您的指令更加模块化和可重复使用。

app.directive("myDir", function($compile) {
  return {
    restrict: 'E',
    scope: {
      user: '=',
      click: '&'
    },
    template: '<a ng-click="click(user)" ><br>{{user.name}}</a>'
  };
});

提示3 :不要使用&#39;替换&#39;,因为它已被弃用。相反,如果必须,请使用元素指令。

Angular会对您应遵循的HTML格式强加一些约定,这可能意味着您的HTML中有一些您不希望在最终HTML中使用的额外标记。但我了解到,考虑到生产率的提高,这是一个很小的代价。