4

http://plnkr.co/edit/ps8TCpQ8znYQnOExO7Er

I have a simple app where I have an Avatar image and a Menu. When you click on the Avatar image I use ng-click, ng-class and ng-show to animate the Menu showing and hiding.

HTML:
<div class="avatar"
     ng-click="id_avatar_menu.getMenuClick('clicked menu')"
     ng-class="{ active: avatarMenuBool }">
     <img width="100" height="100" src="http://www.memes.at/faces/are_you_fucking_kidding_me_clean.jpg" title="avatar" alt="user avatar" />
</div>

<div ng-show="avatarMenuBool" id="avatar_menu">
  <ul>
      <li><a href="#">Profile</a></li>
      <li><a href="#">Account</a></li>
      <li><a href="#">Logout</a></li>
  </ul>
</div>

// ANGULAR
// avatar_menu show/hide boolean
$scope.avatarMenuBool = false;

$scope.id_avatar_menu = {};
$scope.id_avatar_menu.getMenuClick = function(val) {
    $scope.avatarMenuBool = !$scope.avatarMenuBool
    console.log(" ");
    console.log(val);
    console.log("$scope.avatarMenuBool = "+$scope.avatarMenuBool);
};

Now this works, clicking the avatar opens and closes the menu. However I also want to the user to be able to click anywhere else on the body or the #wrapper and close the menu if the menu is open, but not close the menu if the user clicks anywhere inside the menu.

I added some logic into the controller to detect if the menu is open and if the user is clicking inside or outside of the menu. Did not know how to do this in Angular so using raw Javascript here:

document.getElementById('wrapper').onclick = function(e) {

  console.log(" ");

    if(e.target != document.getElementById('avatar_menu')) {

        console.log('clicked outside');
        if ($scope.avatarMenuBool === true) {
            console.log('code to close open avatar menu here...');
            // $scope.id_avatar_menu.setAttribute("class", "ng-hide-add");
        }

    } else {
        console.log("clicked inside menu... don't close menu");
        // Don't do anything...
    }
}

^ Currently does detect if I'm clicking outside or inside the menu, but I don't know how then to force the menu to fade back up if it's open and I clicked outside. Tried that line that is commented out but got errors.

enter image description here

How would you Angularians do this?

Leon Gaban
  • 36,509
  • 115
  • 332
  • 529

1 Answers1

4

Put an ng-click on the page body:

<body ng-app="bitAge" ng-controller="AcctCtrl" ng-click="pageClick()">

And put ng-click on your menu, passing in $event:

<div ng-show="avatarMenuBool" id="avatar_menu" ng-click="menuClick($event)">


Inside your controller:

$scope.pageClick = function () {
    $scope.avatarMenuBool = false;
};

$scope.menuClick = function ($event) {
    $event.stopPropagation();  // stop the event from bubbling up any further
};

You'll also need to pass $event into your getMenuClick() function and stop propagation there as well. See the updated plnkr if you're not sure how to do that.

http://plnkr.co/edit/borj3btjkMIW9oBBzfL9?p=preview

JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • does this prevent links inside the menu from working? according to **[this](http://stackoverflow.com/questions/1403615/use-jquery-to-hide-a-div-when-the-user-clicks-outside-of-it)** the jquery equivalent doesn't work. – mikelt21 Jan 08 '15 at 21:09
  • 1
    @mikelt21 It doesn't appear to be an issue: http://run.plnkr.co/zUdwyYajRFN8NchT/ – JLRishe Jan 08 '15 at 21:15
  • @LeonGaban They seem to work fine when I give them actual URLs. Your links don't have any link destination. – JLRishe Jan 08 '15 at 21:15
  • Ah I updated the pageClick to just `$scope.avatarMenuBool = false;` Now its back to menu open only on Avatar click :) – Leon Gaban Jan 08 '15 at 21:25
  • 1
    @LeonGaban Yup, that was the problem. :) Updated my plnkr link. – JLRishe Jan 08 '15 at 21:26