Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I set a variable when clicking anywhere in the browser window?

Tags:

angularjs

I have a dropdown menu on my site that is controlled by ng-show. When the user clicks on a button they see the dropdown. When they click again, the dropdown is hidden:

<div class="button" ng-click="show = !show">Click Me</div>
<div ng-show="show" ng-init="show = false">
    <div>You can see me now!</div>
</div>

This works fine. But, what I want is for show to be set to false if the user clicks anywhere in the window that is not the div with class "button". How can I achieve this?

like image 867
Chris Paterson Avatar asked Jan 11 '14 22:01

Chris Paterson


3 Answers

Quick/easy way

The quickest/easiest way to do this would be to put your cancellation code (ng-click="show=false") on the body element, and then add $event.stopPropagation() to the existing ng-click. This way, any time you click on the button, since the click event is prevented from propagating upward, the cancellation code wouldn't fire. Clicking anywhere else, though, would fire the ng-click on the body, so that the cancellation code will run. Here's a fiddle that does this.

More 'Angular' way

I think a slightly "better" or "more angular" way to do get the same result would be to create a new click-off directive that can sit alongside ng-click. The new directive could (a) register another click handler on the target element which would stop propagation, and (b) register a click handler on the body element to fire whatever cancellation code you need. Here's a fiddle for that approach.

like image 120
anandthakker Avatar answered Nov 15 '22 09:11

anandthakker


HTML:

<div customDropdown>
  <h4>Click here to see dropdown</h4>
  <ul ng-show="dropdownVisible">
    <li ng-click="doSomething()">Item #1</li>
    <li ng-click="doSomething()">Item #2</li>
    <li ng-click="doSomething()">Item #3</li>
  </ul>
</div>

Simple directive:

app.directive('customDropdown', ['$document', function($document) {
  return {
    restrict: 'A',
    link: function(scope, el) {

      // Switch dropdown visibility by clicking on 'target' element
      el.on('click', function(event) {
        event.preventDefault();
        scope.dropdownVisible = !scope.dropdownVisible;
      });

      // Hide dropdown if clicked somewhere 'outside'
      $document.on('click', function(event) {
        scope.dropdownVisible = false;
        return $document.off('click', event);
      });

    }
  };
}]);
like image 24
Pavlo Shandro Avatar answered Nov 15 '22 07:11

Pavlo Shandro


In this solution:

  • I assume you use jQuery
  • I haven't tested it yet.
  • I use an answer from here: How do I detect a click outside an element?

Create a directive that binds to document click events.

app.directive('clickOnlyHere',function(){

  return {
    scope: {
      clickOnlyHere: "="
    },
    link: function(scope, element, attrs) {

      var clickHandler = function(event){
        // we need to check if the click is within our element ( or its decedents).
        var inside = (element[0] === event.target) || 
                     $(event.target).parents().index(element) !== -1;

        var show = inside ? !scope.clickOnlyHere : false;
        scope.$apply(function() {
          scope.clickOnlyHere = show;
        });
      }

      $(document).on('click', clickHandler);

      // must remove the click handler after our scope is destroyed.
      scope.$on('$destroy',function(){
        $(document).off('click', clickHandler);
      })
    }
  }
});

Use it like so:

<div class="button" click-only-here="show">Click Me</div>
<div ng-show="show" ng-init="show = false">
    <div>You can see me now!</div>
</div>
like image 39
Ilan Frumer Avatar answered Nov 15 '22 09:11

Ilan Frumer