这是该问题的后续问题:具有焦点的AngularJS输入会杀死list的ng-repeat过滤器 基本上,我的代码是使用AngularJS在右侧弹出一个div(抽屉)以过滤事物列表。大多数情况下使用此功能时,UI会被阻止,因此单击该阻止div会关闭抽屉。但是在某些情况下,我们不会阻止用户界面,需要允许用户在抽屉外部单击以取消搜索或选择页面上的其他内容。
我最初的想法是在抽屉打开时附加一个window.onclick处理程序,如果单击除抽屉以外的任何内容,则应关闭抽屉。这就是我将在纯JavaScript应用程序中执行的操作。但是在Angular中,这会有点困难。
下面是此示例中的相关代码。基本上,如果用户在抽屉外单击,我将调用$ scope.toggleSearch,以便将$ scope.open设置回false。
代码可以正常工作,即使$ scope.open从true变为false,它也不会修改DOM。我确定这与事件的生命周期有关,或者当我修改$ scope(因为它是来自单独的事件)时,它是副本而不是原始副本…
最终的目标将是成为最终可重用性的指令。如果有人能指出正确的方向,那我将不胜感激。
$scope.toggleSearch = function () { $scope.open = !$scope.open; if ($scope.open) { $scope.$window.onclick = function (event) { closeSearchWhenClickingElsewhere(event, $scope.toggleSearch); }; } else { $scope.$window.onclick = null; } };
和
function closeSearchWhenClickingElsewhere(event, callbackOnClose) { var clickedElement = event.target; if (!clickedElement) return; var elementClasses = clickedElement.classList; var clickedOnSearchDrawer = elementClasses.contains('handle-right') || elementClasses.contains('drawer-right') || (clickedElement.parentElement !== null && clickedElement.parentElement.classList.contains('drawer-right')); if (!clickedOnSearchDrawer) { callbackOnClose(); } }
抽屉未关闭,因为click事件发生在摘要周期之外,并且Angular不知道$scope.open已更改。要修复它,您可以在$scope.open设置为false后调用$ scope。$apply(),这将触发摘要周期。
$scope.toggleSearch = function () { $scope.open = !$scope.open; if ($scope.open) { $scope.$window.onclick = function (event) { closeSearchWhenClickingElsewhere(event, $scope.toggleSearch); }; } else { $scope.open = false; $scope.$window.onclick = null; $scope.$apply(); //--> trigger digest cycle and make angular aware. } };
这是你的小提琴。
我还尝试为搜索抽屉创建一个指令(如果有帮助的话(它需要一些修复:))。这是一个JSBin。