使用angular指令单项切换

时间:2014-02-11 17:39:11

标签: javascript jquery angularjs angularjs-directive

我有一个“可切换”项目列表。单击“toggleable”元素时,元素将使用ng-show指令进行扩展。如果单击内部项目保持打开状态,但如果您单击其他位置,该项目将收缩。

我实现它的方法是使用一个指令,它公开一个绑定属性isOpen。 isOpen的值在指令链接函数中更改。在元素单击时,isOpen的值设置为true,并将close函数绑定到$ document click事件。如果在元素外部单击,则调用close函数,将isOpen设置为false并取消绑定文档单击事件。

这适用于此指令的单个实例,但如果引入了两个或更多实例,则除了第一次单击之外的每个元素的close函数都无法将相应的isOpen属性设置为false。

这是一个Plunker:http://plnkr.co/edit/ZNTRc2uL73kFZJmYOvhh?p=preview

该指令如下所示:

app.directive('myToggle', ['$document', function ($document) {
    var closeToggle = null;
    return {
        restrict: 'A',
        scope: { isOpen: '=myToggle' },
        link: link
    };

    function link(scope, element, attributes) {
        scope.$on('$locationChangeSuccess', function () { if (closeToggle) closeToggle(); });
        element.bind('click', function() {

            closeToggle = function(event) {
                if (event)
                    if (element.parent().find(event.target).length != 0 && scope.isOpen)
                        return false;

                $document.unbind('click', closeToggle);
                scope.$apply(function () {
                    scope.isOpen = false;
                });
                closeToggle = angular.noop;
            };

            if (!scope.isOpen) {
                scope.$apply(function() {
                    scope.isOpen = true;
                });
                $document.bind('click', closeToggle);
            }
        });
    };
}]);


app.directive('myToggleCard', [function () {
    // Usage:
    // 
    // Creates:
    // 
    var directive = {
        link: link,
        restrict: 'E',
        template: '<a data-my-toggle="isOpen" data-ng-show="!isOpen" href="">ClickMe</a><div data-ng-if="isOpen"> Extra Content </div>',
        replace: true,
        scope: {
        }
    };
    return directive;

    function link(scope, element, attrs) {
        scope.isOpen = false;
    }
}]);

并且html看起来像这样:

<div>
  <div>
      <my-toggle-card></my-toggle-card>
      <my-toggle-card></my-toggle-card>
      <my-toggle-card></my-toggle-card>
      <my-toggle-card></my-toggle-card>  
  </div>
</div>

2 个答案:

答案 0 :(得分:1)

玩弄plunker并记住一篇文章,我在范围,提升和函数声明上阅读了几天,我明白使用函数表达式而不是函数声明可能会导致问题。

我猜测即使它们在同一指令的不同实例中声明,closeToggle函数表达式也会被提升到更高的范围,因此在指令之间共享。

更换

closeToggle = function(event) {

functions closeToggle(event) {

解决了这个问题。 (Plunker:http://plnkr.co/edit/N6p4eU08dfyLLSeotw5S?p=preview

我希望我得到了解决这个问题的原因。我并非100%确定我已经掌握了这些概念,所以欢迎另一个更完整的答案。

答案 1 :(得分:1)

在原始的plunker中,这会使您的函数具有全局范围,因此具有此指令的所有元素都在执行它:

closeToggle = function(event) {

如果您将此功能的范围仅仅与您的指令隔离,就像这样,它将正常工作

var closeToggle = function(event) {