如何防止关闭角度引导下拉(Unbind事件受到指令的约束)

时间:2014-05-16 14:50:35

标签: angularjs angular-ui-bootstrap

我正在使用Angular-Bootstrap Dropdown。我想阻止它关闭点击,直到用户故意关闭它。

默认状态为:单击文档中的某个位置时,Dropdown关闭。

我确定了相关的代码行:(第12行,dropdown.js)

this.open = function( dropdownScope ) {
   if ( !openScope ) {
     $document.bind('click', closeDropdown); // line to unbind
     $document.bind('keydown', escapeKeyBind);
   }
}

您可以在此处找到完整代码:Link to Github

我不想更改angular-bootstrap的原始来源以保持我的项目更新。

我的问题:

如何将指令绑定的事件解除绑定到角度控制器中的文档?

9 个答案:

答案 0 :(得分:136)

我通过在下拉菜单中添加以下内容来解决这个问题。这可以防止关闭下拉,除非您单击打开它的标记

<ul class="dropdown-menu" ng-click="$event.stopPropagation()">

答案 1 :(得分:25)

对于那些使用Angular UI-Bootstrap 0.13.0或更高版本的人来说,这是在UI-Bootstrap文档中说明的更清晰的方式。

  

默认情况下,如果单击任何元素,下拉列表将自动关闭,您可以通过设置自动关闭选项来更改此行为,如下所示:

     
      
  • 始终 - (默认)自动关闭任何下拉列表   单击元素。

  •   
  • outsideClick - 仅在用户时自动关闭下拉列表   单击下拉列表外的任何元素。

  •   
  • 已禁用 - 禁用自动关闭。然后你可以控制   通过使用is-open手动打开/关闭下拉列表。请   请注意,如果单击切换,下拉列表仍会关闭,   按下esc键或打开另一个下拉列表。下拉列表将会   不再关闭$ locationChangeSuccess事件。

  •   

以下是文档的链接: https://angular-ui.github.io/bootstrap/#/dropdown

答案 2 :(得分:3)

这是另一个hack,但你可以添加一个指令来阻止toggle事件传播。例如,像我这样的特定用例:

<div>
<div class="btn-group" dropdown is-open="status.isopen" ng-controller="DropDownCtrl">
  <button type="button" class="btn btn-primary dropdown-toggle" ng-disabled="disabled">
    Button dropdown <span class="caret"></span>
  </button>
  <ul class="dropdown-menu" role="menu">
    <li ng-click="goToPage('Action')">Action</li>
    <li disable-auto-close>Don't Dismiss</li>
    <li ng-click="goToPage('SomethingElse')">Something else here</li>
  </ul>
</div>

将此指令添加到元素应禁用自动关闭行为:

angular.module('plunker', ['ui.bootstrap'])
.controller('DropDownCtrl', ['$scope', '$location',
function($scope, $location) {
  // Controller logic here
  $scope.goToPage = function(page) {
    console.log("Going to " + page + ". Dropdown should close");
    $location.path(page);
  };
}])
.directive('disableAutoClose', function() {
  // directive for disabling the default
  // close on 'click' behavior
  return {
        link: function($scope, $element) {
            $element.on('click', function($event) {
                console.log("Dropdown should not close");
                $event.stopPropagation();
            });
        }
    };
});

Plunker Example Here

答案 3 :(得分:0)

这是一种粗暴的方式。您需要手动控制is-open属性并劫持on-toggle事件,例如:

<div class="btn-group" dropdown is-open="ctrl.isOpen" on-toggle="toggled(open)">
    <button type="button" class="btn btn-primary dropdown-toggle">
        Button dropdown <span class="caret"></span>
    </button>
    <ul class="dropdown-menu" role="menu">
        <li><a href="#">Action</a></li>
        <li><a href="#">Another action</a></li>
        <li><a href="#">Something else here</a></li>
        <li class="divider"></li>
        <li><a href="#">Separated link</a></li>
    </ul>
</div>

控制器:

    $scope.toggled = function (open) {
        $timeout(function () {
            $scope.ctrl.isOpen = true;
        });
    };

我会在dropdownConfig常量(类似于autoClose)上寻求一个永久解决方案的属性。

答案 4 :(得分:0)

根据Rob Jacobs的回答,这是一种更为粗暴的覆盖方式,除了它可以防止丑陋的闪烁ulilcht发表评论:

    $scope.toggled = function (open) {
        $scope.open = true;
        var child = $scope.$$childHead;
        while (child) {
            if (child.focusToggleElement) {
                child.isOpen = true;
                break;
            }
            child = child.$$nextSibling;
        }
    };

答案 5 :(得分:0)

您也可以使用此解决方案:https://gist.github.com/Xspirits/684beb66e2499c3ff0e5 如果需要,可以让您更多地控制下拉列表。

答案 6 :(得分:0)

您可以修饰指令。

通过这种方式,您不必触摸原始代码,您可以保留原始行为。

您可以在下拉列表中放置关闭按钮

<强> HTML

<div class="dropdown-menu keep-dropdown-open-on-click" role="menu">
    <i class="icon-close close-dropdown-on-click"></i>
</div>

<强> JS

angular.module('app').config(uiDropdownMenuDecorate);
uiDropdownMenuDecorate.$inject = ['$provide'];
function uiDropdownMenuDecorate($provide) {

    $provide.decorator('dropdownMenuDirective', uiDropdownMenuDecorator);

    uiDropdownMenuDecorator.$inject = ['$delegate'];

    function uiDropdownMenuDecorator($delegate) {

        var directive = $delegate[0];
        var link = directive.link;

        directive.compile = function () {
            return function (scope, elem, attrs, ctrl) {
                link.apply(this, [scope, elem, attrs, ctrl]);
                elem.click(function (e) {
                    if (elem.hasClass('keep-dropdown-open-on-click') && !angular.element(e.target).hasClass('close-dropdown-on-click')) {
                        e.stopPropagation();
                    }
                });
            };
        };

        return $delegate;
    }
}

答案 7 :(得分:0)

以下是使用经过批准的angular-bootstrap自动关闭方法的代码。请注意,自动关闭属性位于顶部<div>

<div class="btn-group" uib-dropdown auto-close="disabled">
    <button id="single-button" type="button" class="btn btn-primary" uib-dropdown-toggle>
        Button dropdown <span class="caret"></span>
    </button>
    <ul class="dropdown-menu" uib-dropdown-menu role="menu" aria-labelledby="single-button">
        <textarea class="form-control" ng-model="description" rows="4" placeholder="Description"></textarea>
    </ul>
</div>

答案 8 :(得分:0)

您可以通过添加事件传播来阻止事件在Ang Tree 2和更高版本的DOM树中冒泡。 例如:(click)=“ $ event.stopPropagation()”