AngularJS dropdown directive hide when clicking outside

后端 未结 9 2132
长发绾君心
长发绾君心 2020-11-29 22:06

I\'m trying to create a multiselect dropdown list with checkbox and filter option. I\'m trying to get the list hidden with I click outside but could not figure it out how. A

9条回答
  •  感动是毒
    2020-11-29 22:41

    I was not totally satisfied with the answers provided so I made my own. Improvements:

    • More defensive updating of the scope. Will check to see if a apply/digest is already in progress
    • div will also close when the user presses the escape key
    • window events are unbound when the div is closed (prevents leaks)
    • window events are unbound when the scope is destroyed (prevents leaks)

      function link(scope, $element, attributes, $window) {

      var el = $element[0],
          $$window = angular.element($window);
      
      function onClick(event) {
          console.log('window clicked');
      
          // might need to polyfill node.contains
          if (el.contains(event.target)) {
              console.log('click inside element');
              return;
      
          }
      
          scope.isActive = !scope.isActive;
          if (!scope.$$phase) {
              scope.$apply();
          }
      }
      
      function onKeyUp(event) {
      
          if (event.keyCode !== 27) {
              return;
          }
      
          console.log('escape pressed');
      
          scope.isActive = false;
          if (!scope.$$phase) {
              scope.$apply();
          }
      }
      
      function bindCloseHandler() {
          console.log('binding window click event');
          $$window.on('click', onClick);
          $$window.on('keyup', onKeyUp);
      }
      
      function unbindCloseHandler() {
          console.log('unbinding window click event');
          $$window.off('click', onClick);
          $$window.off('keyup', onKeyUp);
      }
      
      scope.$watch('isActive', function(newValue, oldValue) {
          if (newValue) {
              bindCloseHandler();
          } else {
              unbindCloseHandler();
          }
      });
      
      // prevent leaks - destroy handlers when scope is destroyed
      scope.$on('$destroy', function() {
          unbindCloseHandler();
      });
      

      }

    I get $window directly into the link function. However, you do not need to do this exactly to get $window.

    function directive($window) {
        return {
            restrict: 'AE',
            link: function(scope, $element, attributes) {
                link.call(null, scope, $element, attributes, $window);
            }
        };
    }
    

提交回复
热议问题