在指令中使用ng-show时必须强制使用scope.apply

时间:2014-05-10 11:26:27

标签: angularjs angularjs-directive

所以我正在编写一个简单的工具提示指令,您可以将指令应用于您想要工具提示的项目。然后构建并将工具提示附加到您已应用指令的标记上。规范要求它是基于点击而不是悬停,所以有一些简单的监听器来显示/隐藏内容。这听起来很简单,但是当我改变状态以在元素click-hanlder中显示时,角度事件循环不会触发,因为角度事件循环不会触发,除非我强制使用scope.apply。同样适用于隐藏,但我通过将所有代码放入ng-click来管理解决方法。

好的说说,这是代码:

应用指令的基本标记

<i tooltip text="I'm a tooltip">Target</i>

这是指令

app.directive('tooltip', function() {
return {
    restrict: 'EA',
    transclude: true,
    scope: {
        text: '@'
    },
    template: '<span ng-transclude></span>' + 
    '<i class="tooltip-arrow icon-arrow-up2" ng-show="state.display"></i>' + 
    '<div class="tooltip-container" ng-show="state.display">' + 
    '<span class="tooltip-close" ng-click="state.display = false; $event.stopPropagation();">X</span>' +
    '<p>{{text}}</p></div>',
    controller: function($scope, $element) {
        $scope.state = {
            display: false,
        };


        $element.on('click', function(e) {
            $scope.state.display = true;

            // WHY AM I NEEDED?
            $scope.$apply();

        });
    }
};
});

这是演示的plunkr,只需删除scope.apply,它就会停止工作,直到你做一些事情来触发事件循环:

http://plnkr.co/edit/mmSAVKkXfIBsoVz9XSKZ

这是一个错误还是我在角度文档中遗漏了一些小问题?

2 个答案:

答案 0 :(得分:1)

使用非角度事件时需要

scope.$apply()elm.on(...)是jQuery的一部分,因此angular无法捕捉到变化。 ng-click否则是角度的一部分,所以你不需要应用任何东西。

答案 1 :(得分:0)

Derp,当然在发布之后我发现将点击监听器放在这个人身上

<span ng-transclude ng-click="state.display = true"> 

无需任何scope.apply即可正常工作。如果我不必使用angular.element来设置点击监听器,我认为它也是更好的代码。