AngularJS-将函数传递给指令


160

我有一个angularJS示例

<div ng-controller="testCtrl">

<test color1="color1" updateFn="updateFn()"></test>
</div>
 <script>
  angular.module('dr', [])
.controller("testCtrl", function($scope) {
    $scope.color1 = "color";
    $scope.updateFn = function() {
        alert('123');
    }
})
.directive('test', function() {
    return {
        restrict: 'E',
        scope: {color1: '=',
                updateFn: '&'},
        template: "<button ng-click='updateFn()'>Click</button>",
        replace: true,
        link: function(scope, elm, attrs) { 
        }
    }
});

</script>
</body>

</html>

我想当我单击按钮时,将出现警报框,但什么也没显示。

谁能帮我?

Answers:


243

要从隔离作用域指令内部在父作用域中调用控制器函数,请dash-separated在HTML中使用属性名称,如OP所述。

另外,如果要向函数发送参数,请通过传递对象来调用函数:

<test color1="color1" update-fn="updateFn(msg)"></test>

JS

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

app.controller("testCtrl", function($scope) {
    $scope.color1 = "color";
    $scope.updateFn = function(msg) {        
        alert(msg);
    }
});

app.directive('test', function() {
    return {
        restrict: 'E',
        scope: {
            color1: '=',
            updateFn: '&'
        },
        // object is passed while making the call
        template: "<button ng-click='updateFn({msg : \"Hello World!\"})'>
            Click</button>",
        replace: true,        
        link: function(scope, elm, attrs) {             
        }
    }
});

Fiddle


1
感谢Codezilla的回答,当我想将功能“ updateFn”与父作用域绑定以隔离指令“ test”中的作用域时,我想问一下这种情况,这可能吗?
user2707026 2013年

2
replace属性已过时,AngularJS:stackoverflow.com/questions/24194972/...
cdmckay

8
由于某种原因,该参数对我来说是不确定的。
chovy

1
@chovy我认为仅在您再次调用该方法时才使用该参数?第一次使用方括号的用法似乎是angular希望该方法通过的格式,但是我可能在这里是错的
marksyzm 2015年

1
updateFn({msg: 'my message'});在指令的link函数内进行函数调用时,必须以该格式使用对象映射。
布赖恩(Brian

159

也许我错过了一些东西,但是尽管其他解决方案确实调用了父作用域函数,但无法从指令代码传递参数,这是因为,例如,使用固定参数进行update-fn调用。稍作更改即可使指令传递参数,我认为这会有用得多。updateFn(){msg: "Hello World"}

<test color1="color1" update-fn="updateFn"></test>

请注意,HTML正在传递函数引用,即不带()括号。

JS

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

app.controller("testCtrl", function($scope) {
    $scope.color1 = "color";
    $scope.updateFn = function(msg) {        
        alert(msg);
    }
});

app.directive('test', function() {
    return {
        restrict: 'E',
        scope: {
            color1: '=',
            updateFn: '&'
        },
        // object is passed while making the call
        template: "<button ng-click='callUpdate()'>
            Click</button>",
        replace: true,        
        link: function(scope, elm, attrs) {       
          scope.callUpdate = function() {
            scope.updateFn()("Directive Args");
          }
        }
    }
});

因此,在上面的代码中,HTML调用了本地作用域callUpdate函数,该函数随后从父作用域“获取” updateFn,并使用指令可以生成的参数调用返回的函数。

http://jsfiddle.net/mygknek2/


9
不知道我该如何对某些有效的方法投下反对票?如果投反对票,您应该发表评论。
史蒂夫2015年

7
这对我有用。如果您不想要额外的功能,只需编写ng-click="updateFn()('Directive Args')"
Graham Walters 2015年

7
噢!scope.updateFn()(“ Args指令”); !! 不是scope.updateFn(“指令Args”); !!!
Phung D.

2
这确实是一个更完美的答案!
vinesh

11
@ Ludwik11肯定-这是因为scope.updateFn像这样定义时是一个返回函数的函数(因此()()),这是因为我们通过html的update-fn =“ updateFn”传入了范围到我们要调用的函数。第一个()是对angular的调用,以返回此引用,第二个()是对函数的调用,也是我们传递任何参数的地方。HTH
史蒂夫(Steve)

39

在“测试”指令Html标记中,函数的属性名称不应为驼峰式,而基于破折号。

所以-代替:

<test color1="color1" updateFn="updateFn()"></test>

写:

<test color1="color1" update-fn="updateFn()"></test>

这是angular区分指令属性(例如update-fn函数)和函数之间差异的方法。


1
谢谢你的收获。我已将其包括在我的答案中。投票了!:)
AlwaysALearner 2014年

10

如何通过双向绑定传递控制器功能?然后,您可以在指令中使用它,就像在常规模板中一样使用它(为简单起见,我剥离了不相关的部分):

<div ng-controller="testCtrl">

   <!-- pass the function with no arguments -->
   <test color1="color1" update-fn="updateFn"></test>
</div>

<script>
   angular.module('dr', [])
   .controller("testCtrl", function($scope) {
      $scope.updateFn = function(msg) {
         alert(msg);
      }
   })
   .directive('test', function() {
      return {
         scope: {
            updateFn: '=' // '=' bidirectional binding
         },
         template: "<button ng-click='updateFn(1337)'>Click</button>"
      }
   });
</script>

我着手解决这个问题,因为我尝试了将上述方法禁用,但是以某种方式却无效。现在,它可以完美运行了。


5

使用破折号和小写字母表示属性名称(就像说的其他答案一样):

 <test color1="color1" update-fn="updateFn()"></test>

并在指令范围内使用“ =”代替“&”:

 scope: { updateFn: '='}

然后,您可以像其他任何函数一样使用updateFn:

 <button ng-click='updateFn()'>Click</button>

你去!


5
为什么要使用'='而不是'&'?当我尝试这样做时,它会不断重复调用我的函数。
user1012500 '16

2
为此使用“ =”是错误的。那是两种方式的对象绑定。
Ben Taliadoros

1
我认为,唯一的问题是在第一个模板中使用括号。这将执行函数,然后绑定结果。相反,你应该传递给函数的名称即可,如下所示:update-fn="updateFn"
马顿陶

1
错误的答案。很坏。
拖曳

4

我必须使用“ =”绑定而不是“&”,因为这不起作用。奇怪的行为。


2
这是因为您最有可能将JS函数引用而不是执行传递给该指令。当您将该函数作为指令的参数传递时,update-fn="updateFn()"必须包括括号(可能还有params)。将其作为函数引用传递update-fn="updateFn"将不适用于&绑定
JorgeGRC

0

@JorgeGRC感谢您的回答。不过,有一件事,“也许”部分非常重要。如果确实有参数,则还必须在模板中包括该参数,并确保指定您的本地参数,例如updateFn({msg: "Directive Args"}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.