1

I created a button

<button type="button" ng-click="chooseOptions()" id="chooseOptionButton" ng-bind="whatToDisplay()"></button>

Which shows a <div ng-show=appearOnChoice>on click and toggles back when clicking again!

 $scope.chooseOptions=function(){
    $scope.appearOnChoice=!$scope.appearOnChoice;

  }

However, I also want this element to hide again, when the user clicks anywhere outside this div element. How can I do this? I need strictly stick with AngularJS and not use jQuery.

Hope you can help me with that.

EDIT: I tried to adapt some of the events of bootstrap datepicker, but I am not sure how to apply it properly

 $scope.$on('datepicker.focus', focusElement);
 scope.$watch('isOpen', function(value) {
        if (value) {
          scope.$broadcast('datepicker.focus');
          scope.position = appendToBody ? $position.offset(element) : $position.position(element);
          scope.position.top = scope.position.top + element.prop('offsetHeight');

          $document.bind('click', documentClickBind);
        } else {
          $document.unbind('click', documentClickBind);
        }
      });
  var focusElement = function() {
    $timeout(function() {
      self.element[0].focus();
    }, 0 , false);
  };

How can I adapt this to my case?!

Dribel
  • 465
  • 1
  • 10
  • 24

4 Answers4

1

I think that you dont have to write a function, you can use ng-init to create a model, ng-show to show/hide the div based on the value of the model, and with ng-click change the value of the model. See example below:

var myapp = angular.module('myapp',[]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myapp">
<div ng-init="showDiv = true;" >
  <div ng-show="showDiv"> SHOOOOOOOOW </div>
  <button ng-click="showDiv = !showDiv;">Click me</button>
</div>
</div>

You can set the model value to be false when the user is clicking everywhere else, and set it again to true when it clicks the button. If you made a fiddle I can help you easier :)

Avraam Mavridis
  • 8,698
  • 19
  • 79
  • 133
  • True, but again, how do you set it to false when clicking everywhere else unless you add an `ng-click="showDiv=false"` directive on every clickable element that is not the div? – Beartums Dec 02 '14 at 12:05
  • But how can I define "everywhere else"? – Dribel Dec 02 '14 at 12:35
  • Event Propagation, with appropriate stopPropagation commands, should be able to do this with a ng-click on the outer div, but I think I read somewhere that angular wasn't handling stopPropagation properly. Haven't been able to come up with a reference, though. EDIT: my statement is wrong. stopPropagation can be handled through $event. Check out this answer [http://stackoverflow.com/questions/20300866/angularjs-ng-click-stoppropagation](http://stackoverflow.com/questions/20300866/angularjs-ng-click-stoppropagation) – Beartums Dec 02 '14 at 12:43
  • @user3383709 as Beartums said you can achieve that with Event Propagation, I dont know exactly the structure of your html/app so I am not sure where you have to add the ng-click – Avraam Mavridis Dec 02 '14 at 15:52
0

If the DIV has focus, then you can use the ng-blur directive on the DIV to run set appearOnChoice to false. However, if the DIV does not already have focus (which it won't if you are depending on the button to make it visible), you will need to manipulate the DOM in your code (to provide focus) OR create a custom directive to set focus so that the ng-blur directive will work. Check out possibilities for that with this link.

alternatively, you can add an ng-click directive to every clickable object on your view that will hide the DIV when fired. But I don't really think that's the best way to go...

Community
  • 1
  • 1
Beartums
  • 1,340
  • 1
  • 10
  • 15
  • I am getting closer to your solution. The blur of course is a great idea. But I should mention that once the div is visible and I click on it, the button loses its focus and at the same time the div does not get the focus either. Therefore, it does not seem to be possible this way. – Dribel Dec 02 '14 at 13:07
  • I think that's one of the basic problems. It would be nice to simply set the focus on the div through the DOM. I'm not actually sure if you can set the focus on a div by clicking, since it in not an input element. EDIT: adding a tabindex to the div might help. Check out [this link](http://stackoverflow.com/a/148444/2719246) – Beartums Dec 02 '14 at 13:15
0

The easiest and cleanest way to handle the click away is to register and event on the document that will remove the element when anything other than it, or its children, are clicked.

For an example of a service that does this see GitHub EnzeyNet/Services

Sorry about the lack of documentation there but after injecting the service you would use it like this.

var divElem
nzService.registerClickAwayAction(function() {
    divElem.remove();
}, divElem);
Enzey
  • 5,254
  • 1
  • 18
  • 20
0

I simply solved it by using a ui bootstrap dropdown. This comes along with an is-open option and closes on click outside.

Dribel
  • 465
  • 1
  • 10
  • 24