Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular.js closing with click anywhere but on the element

It's pretty common thing, like if you click on inbox here here on stackoverflow. I'll be calling that dialog or whatever gets opened a thing.

Now there are two ways I know of to deal with this,

  1. you create an invisible overlay where only the element you opened has bigger zindex, and you close your thing by clicking on the overlay
  2. click event on the document, and you check upon clicking whether you clicked on your thing or outside it, in which case you close your thing.

In either case I'd ideally like to use ng-class to add/remove class that would show/hide the thing.

Now how would I do this with angular, so it could be used on any component(thing) I might add. It's not like I have single modal, I might have quite a few different components, with different html structure, positioning and stuff.

Which approach would be better, document event, overlay or something completely else?

Since angular doesn't really have any reference to dom, document approach could be a problem, right, since I can't quite check whether I'm clicking on the thing element? Unless I'd give every thing the same class..

Overlay approach on the other hand doesn't require any reference to dom elements.

Both approaches would need a unique var at rootScope for that ng-class to work.. which bring the question whether to use ng-class or something custom..

Anyway just throwing my ideas out there, maybe I'm thinking about it wrong from the beginning, has anyone dealt with this before?

like image 940
fxck Avatar asked Dec 11 '22 08:12

fxck


1 Answers

The way I've tackled things like this before is using inheritedData to communicate to the click handler whether it's in or out of the thing:

  • In the custom directive for the thing, add a data variable to the element, using jqLite data, say element.data('myThing',true) . If you want to distinguish between multiple instances of the the thing, you might need to use some uniquely generated key.

  • In the same custom directive, in a click event handler on document.body, you can check angular.element(event.target).inheritedData('myThing')

An example directive that uses this technique is below

app.directive('thing', function($document,$window) {
  return {
    restrict: 'E',
    template: '<div><span>Inner thing</span></div>',
    replace: true,
    link: function(scope,element) {
      element.data('thing',true);

      angular.element($document[0].body).on('click',function(e) {
        var inThing =  angular.element(e.target).inheritedData('thing');
        if (inThing) {
          $window.alert('in');
        } else {
          $window.alert('out');
        }
      })
    }
  }
});

and can be seen in this Plunker http://plnkr.co/edit/bRDLcLoesM7Z0BIxKxYu?p=preview

like image 173
Michal Charemza Avatar answered Dec 29 '22 04:12

Michal Charemza