Not sure how to hide a div when clicking OUTSIDE of the div

前端 未结 4 530
挽巷
挽巷 2020-12-23 17:20

This is a follow-up question to this question: AngularJS input with focus kills ng-repeat filter of list

Basically my code is using AngularJS to pop-out a div (a dra

相关标签:
4条回答
  • 2020-12-23 17:41

    The drawer is not closing because the click event occurs outside the digest cycle and Angular doesn't know that $scope.open has changed. To fix it you can call $scope.$apply() after $scope.open is set to false, this will trigger the digest cycle.

    $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. 
        }
    };
    

    Here is your Fiddle.

    I was also trying to create a directive for the search drawer, if it helps (it needs some fixes :)). Here is a JSBin.

    0 讨论(0)
  • 2020-12-23 17:42

    I couldn't find a solution i was 100% happy with, this is what i used:

    <div class="options">
        <span ng-click="toggleAccountMenu($event)">{{ email }}</span>
        <div ng-show="accountMenu" class="accountMenu">
            <a ng-click="go('account')">Account</a>
            <a ng-click="go('logout')">Log Out</a>
        </div>
    </div>
    

    the span with ng-click is used to open the menu, the div.accountMenu is toggled open or closed

    $scope.accountMenu = false;
    $scope.toggleAccountMenu = function(e){
        if(e) e.stopPropagation();
        $scope.accountMenu = !$scope.accountMenu;
        if ($scope.accountMenu) {
            $window.onclick = function(e) {
                var target = $(e.target);
                if(!target) return;
                if(!target.hasClass('accountMenu') && !target.is($('.accountMenu').children())){
                    $scope.toggleAccountMenu();
                }               
            };
        } else if (!e) {
            $window.onclick = null;
            $scope.$apply();
        }
    }
    

    This uses jQuery for child checking but you can probably do it without if needed.

    I was getting some nasty errors with other peoples version, like trying to call $apply() when its already in a cycle, my version prevents propagation and safe-checks against $apply()

    0 讨论(0)
  • 2020-12-23 17:56

    The accepted answer will throw an error if you click on the button to close the drawer/popup, and the button is located outside of it, because $apply() will be executed twice.

    This is a simplified version, that doesn't need call the whole toggleSearch() function again and prevents the double $apply().

    $scope.toggleSearch = function() {
    
      $scope.open = !$scope.open;
    
      if ($scope.open) {
        $window.onclick = function(event) {
          var clickedElement = event.target;
          if (!clickedElement) return;
    
          var clickedOnSearchDrawer = elementClasses.contains('handle-right') || elementClasses.contains('drawer-right') || (clickedElement.parentElement !== null && clickedElement.parentElement.classList.contains('drawer-right'));
    
          if (!clickedOnSearchDrawer) {
            $scope.open = !$scope.open;
            $window.onclick = null;
            $scope.$apply();
          }
        }
      } else {
        $window.onclick = null;
      }
    };
    
    0 讨论(0)
  • 2020-12-23 18:04

    I suggest to add $event.stopPropagation(); on the view right after on the ng-click. You don't need to use jQuery.

    <button ng-click="toggleSearch();$event.stopPropagation();">toggle</button>
    

    Then, you can use this simplified js.

    $scope.toggleSearch = function () {
        $window.onclick = null;
        $scope.menuOpen = !$scope.menuOpen;
    
        if ($scope.model.menuOpen) {
            $window.onclick = function (event) {
                $scope.menuOpen = false;
                $scope.$apply();
            };
        }
    };
    
    0 讨论(0)
提交回复
热议问题