Javascript 在AngularJS指令内调用传入函数

Javascript 在AngularJS指令内调用传入函数,javascript,angularjs,angularjs-directive,Javascript,Angularjs,Angularjs Directive,我正在创建一个drag指令,将事件侦听器添加到dragstart事件。我想将一个函数从控制器传递到指令。当我添加事件侦听器时,它不会调用传入的函数 这是我的控制器: angular.module('testApp').controller('testCtrl', [testCtrl]); function testCtrl() { var vm = this; vm.dragStart = dragStart; function dragStart(e){

我正在创建一个drag指令,将事件侦听器添加到dragstart事件。我想将一个函数从控制器传递到指令。当我添加事件侦听器时,它不会调用传入的函数

这是我的控制器:

angular.module('testApp').controller('testCtrl', [testCtrl]);

function testCtrl() {
    var vm = this;
    vm.dragStart = dragStart;

    function dragStart(e){
        alert('drag started!', e);
    }

}
这是我的指示:

angular.module('testApp').directive('testDraggable', function(){
    var directive = {
        scope: {
            dragStart: '&',
        },
        restrict: 'A',
        link: link
    };

    function link(scope, element, attrs){
        var dragStartCallback = function(event){
            alert('dragStartCallback!');
            scope.dragStart({e: event});
        }

        element[0].addEventListener('dragstart', dragStartCallback, false);
    }
    return directive;
});
我遇到的问题是调用了dragStartCallback函数,但从未调用过内部scope.dragStart函数。我读过关于映射参数的书,这是我正在做的,但仍然失败。在dragStartCallback中,我也正确地传递了事件。如果有更好的方法来做这件事,任何建议都将不胜感激


提前感谢您的任何意见。这里有一个JS Fiddle:

在指令范围绑定中使用名称
dragStart
有问题。将其更改为其他内容,您的代码将正常工作

var directive = {
    scope: {
        ds: '&',
    },

正如@miensol所指出的,这是由于以下文件中记录的一项更改:

指令不能以-start或-end结尾 此更改对于启用多元素指令是必要的。最好的修复方法是重命名现有的指令,这样它们就不会以这些后缀结尾


显然,这也适用于属性。

如@j.wittwer所述,如果您更改范围绑定的名称,即

scope: {
  dragStart:'&startDragging'
}
然后在指令中使用它作为
start dragging=“vm.startDrag(e)”
它将工作

var directive = {
    scope: {
        ds: '&',
    },
这与
ng repeat
(版本1.2)中引入的一项功能有关,在该功能中,您可以使用
ng repeat start
ng repeat end
在重复元素中定义页眉主体和页脚。您可以在中找到有关此语法的更多信息

似乎相当不幸的是,影响angular(至少在1.2.1版中)中的所有指令(和属性)的这一更改只在中提到过,而且很容易被忽略,特别是当您不知道要查找什么时

然而,了解为什么会出现这种行为是很有趣的

罪魁祸首代码可以在
集合指令中找到(版本1.2.1中的第5600行),您可以看到:

var directiveNName = ngAttrName.replace(/(Start|End)$/, '');
if (ngAttrName === directiveNName + 'Start') {
    attrStartName = name;
    attrEndName = name.substr(0, name.length - 5) + 'end';
    name = name.substr(0, name.length - 6);
}
在中,所述代码更改为:

var directiveNName = ngAttrName.replace(/(Start|End)$/, '');
if (directiveIsMultiElement(directiveNName)) {
    if (ngAttrName === directiveNName + 'Start') {

因此,所讨论的行为只会影响具有
multi-element:true
的指令,这是在中引入的更改。

@j.wittwer是正确的,它与元素属性的名称
dragStart
有关,但不是因为名称,这是因为出于某种原因,Angular在将函数传递给指令属性时不喜欢连字符属性。这仅在将父控制器函数传递给指令时发生。如果您将其设置为
dragstart
而不是
dragstart
,则它将正常工作,当然,您的指令需要具有:

scope : {
    ds : '&dragstart'
}

在我的实际代码中,我的作用域函数不是名为handleDragStart的示例,即使将指令作用域重命名为ds,它也不会执行。因此,这两个名字是问题所在。@j.wittwer刚刚补充了更多关于这种行为的信息。