4

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?

fxck
  • 4,898
  • 8
  • 56
  • 94
  • take a look at this, it may help you http://fundoo-solutions.github.io/angularjs-modal-service/ – Misters Jan 27 '14 at 16:05
  • I'd go with a custom directive and click event on document. – Florian F. Jan 27 '14 at 16:22
  • how would you know that it should not close upon clicking on the thing element? with that always-the-same-class? isn't any kind of DOM searching quite against angular ways? – fxck Jan 27 '14 at 16:28
  • possible duplicate of [Click everywhere but here event](http://stackoverflow.com/questions/12931369/click-everywhere-but-here-event) – fxck May 02 '14 at 16:46

1 Answers1

13

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

Michal Charemza
  • 25,940
  • 14
  • 98
  • 165