Search code examples
javascriptangularjsangularjs-ng-clickng-showng-hide

How to manually ng-hide something from inside a Controller?


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?


Solution

  • 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