Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angularjs 测试指令中单击主体的角度最大的方法是什么?_Angularjs_Angularjs Directive - Fatal编程技术网

Angularjs 测试指令中单击主体的角度最大的方法是什么?

Angularjs 测试指令中单击主体的角度最大的方法是什么?,angularjs,angularjs-directive,Angularjs,Angularjs Directive,我有一个应用于导航元素的小下拉指令。如果用户通过设置$scope.menu.visible=false单击导航元素之外的任何位置,我希望关闭下拉列表 在Angular指令中检查body元素上的单击或按键的角度最大的方法是什么 我目前的指令如下所示: angular.module('dropdowns', []) .directive('dropdown', function () { return { scope: true, link: function (

我有一个应用于导航元素的小下拉指令。如果用户通过设置
$scope.menu.visible=false
单击导航元素之外的任何位置,我希望关闭下拉列表

在Angular指令中检查body元素上的单击或按键的角度最大的方法是什么

我目前的指令如下所示:

angular.module('dropdowns', [])
  .directive('dropdown', function () {
    return {
      scope: true,
      link: function (scope, element) {
        var body = angular.element('body');
        var clickOutside = function (e) {
          var target = angular.element(e.target);
          if (!$.contains(element, target)) {
            scope.menu.visible = false;
          }
        }
        body.on('click', clickOutside);
        // body.on('keyup', scope.escapeKey);
      },
      controller: function($scope) {
        $scope.menu = {visible: false};
        $scope.hide = function () {
          $scope.menu.visible = false;
        };

        $scope.show = function () {
          scope.menu.visible = true;
        };

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

        $scope.escapeKey = function (e) {
          if (e.which === 27) {
            $scope.hide();
          }
        };
      }
    };
  });
使用以下模板片段设置下拉列表:

<nav dropdown>
  <a ng-click="toggle()">Menu</a>
  <ul ng-show="menu.visible">
    ...
  </ul>
</nav>

菜单
    ...

似乎是显而易见的选择。但是,请确保您的
ng应用程序
指令已打开
,以便将
包含在应用程序中。

最有角度的方式: 将其添加到指令中。示例:将单击事件属性添加到“body”标记 比如:

angular.module('directive_name', []).directive('clickEvents', [
    '$rootScope',
    '$document',
  function($rootScope, $document) {
    return {
      link: function() {
        $document.bind('click', function(event) {
          $rootScope.$broadcast('click', event);
        });
      }
    };
  }
]);

module.directive('directive_name', [
  function() {
    return {
      link: function(scope, element, attributes) {
        scope.$on('click', function(onEvent, clickEvent) {
          scope.clicked = true;
        });
      }
    };
  }
]);
不知道“最有棱角的方式”,但可能是最简单的。 假设您的模板中有类似的内容

<ul class="dropdown-menu keep_open">
    <li>....
我是相关的普朗克



您的实现看起来相当不错,但我真的要研究一下下拉菜单的引导实现


在您的案例中,您需要做的就是在下拉指令元素级别停止事件传播。Body元素将处理指向它的单击事件。下面是您的指令的链接功能的外观:

link: function(scope, element) {

    var body = angular.element('body');

    body.on('click', function(e) {
        scope.$apply(function() {
            scope.menu.visible = false;
        });
    });

    element.on('click', function(e) {
        e.stopPropagation();
    });

    // body.on('keyup', scope.escapeKey);
},

演示:我将分享我的最终代码,以防它对其他人有用。这里有一些很好的提示,例如从rootScope广播和使用stopPropagation。我的结局是这样的。单击下拉列表中未包含的任何元素或按escape键时,它将关闭

我最终在闭包中保留了对body的引用,因此每个下拉列表都保留了它自己的引用,它仍然需要一个select,但变得独立,这是一个额外的好处

angular.module('dropdowns', [])
  .directive('dropdown', function () {
    return {
      scope: true,
      link: function (scope, element) {

        scope.menu = {
          visible: false
        };

        scope.hide = function () {
          scope.menu.visible = false;
        };

        scope.show = function () {
          scope.menu.visible = true;
        };

        scope.toggle = function (e) {
          scope.menu.visible = !scope.menu.visible;
        };

        var escapeKey = function (e) {
          if (e.which === 27) {
            scope.hide();
            scope.$apply();
          }
        };

        var clickOutside = function (e) {
          if (!$.contains(element[0], e.target)) {
            scope.hide();
            scope.$apply();
          }
        }
        var body = angular.element('body');
        body.on('click', clickOutside);
        body.on('keyup', escapeKey);

      }
    };
  });

这可以正常工作,但无法访问下拉菜单$scope,假设页面上有多个下拉菜单。在这种情况下,您应该稍微修改一下指令。发布其代码。您好@dfsq,代码已发布。如您所见,我在这里使用jQuery来选择链接函数中的body元素,违反了“don't select,direct”的精神。您如何在HTML中使用您的指令?如何打开下拉列表?@dfsq-好问题,我已经发布了模板。这是标准的东西。最初我的指令中有更多内容,但当涉及到进行更改时,我发现这限制了我的选择。看看理想方法的简单程度。StopRoppagation的缺点是,如果我有多个下拉列表(我有),并且我单击了第二个,第一个将保持打开状态。不,其他的将关闭。我编辑了我的答案,请参阅相关的plunker:)哦,嘿,这很好,那么该指令只需要知道$rootScope,这是一个简单的DI。当然,试试看,你会发现:)看起来不错,但就我个人而言,如果我不必污染$rootScope,并且节省使用事件。它很好,但在多个nav下拉列表中失败,即,单击一个导航元素不会关闭页面其他位置的其他导航元素。
link: function(scope, element) {

    var body = angular.element('body');

    body.on('click', function(e) {
        scope.$apply(function() {
            scope.menu.visible = false;
        });
    });

    element.on('click', function(e) {
        e.stopPropagation();
    });

    // body.on('keyup', scope.escapeKey);
},
angular.module('dropdowns', [])
  .directive('dropdown', function () {
    return {
      scope: true,
      link: function (scope, element) {

        scope.menu = {
          visible: false
        };

        scope.hide = function () {
          scope.menu.visible = false;
        };

        scope.show = function () {
          scope.menu.visible = true;
        };

        scope.toggle = function (e) {
          scope.menu.visible = !scope.menu.visible;
        };

        var escapeKey = function (e) {
          if (e.which === 27) {
            scope.hide();
            scope.$apply();
          }
        };

        var clickOutside = function (e) {
          if (!$.contains(element[0], e.target)) {
            scope.hide();
            scope.$apply();
          }
        }
        var body = angular.element('body');
        body.on('click', clickOutside);
        body.on('keyup', escapeKey);

      }
    };
  });