Angular指令,将click事件绑定到外部元素不起作用

时间:2014-10-20 10:57:59

标签: javascript html angularjs angularjs-directive angularjs-scope

我正在尝试使用Angular创建自定义事件以切换。该指令被称为可切换。

一开始听起来微不足道,但棘手的是我希望能够使用页面上的任何按钮或链接进行切换。

我写的代码如下

指令

'use strict';

angular.module('onsComponents')
.directive('togglable', function() {
return {
  restrict: 'A',
  transclude: true,
  scope: {
    togglerId: '@',
    show: '@'
  },
  link: function(scope, element, attrs) {
    if (!scope.togglerId) {
      console.error("Toggler id must be given")
      return
    }

    scope.visible = (scope.show === 'true')
    scope.toggle = function() {
      alert("Before " + scope.visible)
      scope.visible = !scope.visible
      alert("After " + scope.visible)
    }

    //Bind click event to given dom element
    angular.element('#' + scope.togglerId).bind("click", function() {
      scope.toggle()
    })


  },
  templateUrl: 'app/components/toggler/toggler.html'
  }
  })

模板

<div ng-transclude ng-show="visible">

</div>

视图

<a href="" id="toggleButton" >Click me to toggle</a>
<div togglable toggler-id="toggleButton">
  Hey
</div>

切换链接似乎正在运行。单击链接时,我可以看到警报。麻烦的是内容没有出现。看起来链接与内容的范围不同,在我这样做时会创建另一个范围。

如果我移动模板中的点击链接,如下所示,它可以正常工作。但那不是我想要的。

<!-- Move the link inside template -->
<a href=""  ng-click="toggle()" >Click me to toggle</a>
<div ng-transclude ng-show="visible">

</div>

那我怎么能实现呢?

2 个答案:

答案 0 :(得分:2)

更多 angular-esque 创建两个指令和一个为此目的链接它们的服务。粗略概述:

app.service('toggleService', function() {
    var toggleables = {};

    this.registerToggleable = function(key, f) {
        toggleables[key] = f;
    }

    this.toggle = function(key) {
        var f = toggleables[key];
        f();
    }
});

app.directive('toggler', function(toggleService) {
    return {
        link: function(scope, elem, attrs) {
            elem.bind("click", function() {
                toggleService.toggle(attrs.toggler);
                // because the event handler operates outside of angular digest cycle
                scope.$apply();
            });
        }
    }
})

app.directive('toggleable', function(toggleService) {
    return {
        link: function(scope, elem, attrs) {
            function toggle() {
                scope.visible = !scope.visible;
            }

            toggleService.registerToggleable(attrs.toggleable, toggle);
        }
    }
});

除了在示波器上设置变量之外,上面需要调整实际,但是你可以像这样使用这两个:

<a href="" toggler="foo" >Click me to toggle</a>
<div toggleable="foo">
  Hey
</div>

通过这种方式,您可以在元素本身上声明切换功能,而不会使用基于ID的查找魔法。

答案 1 :(得分:1)

每当你改变Angular在Angular外面外面的东西时,你都要调用scope.$apply()。通过 outside 我指的是使用jQuery API绑定的事件 - 或者除了Angular的本地ng-click之外的任何其他方式等。

所以要么:

scope.toggle = function() {
    scope.visible = !scope.visible;
    scope.$apply();
}

或者:

scope.toggle = function() {
    scope.$apply(function() {
        scope.visible = !scope.visible;
    });
}