title: How can I close a dropdown on click outside?
body: <p>I would like to close my login menu dropdown when the user click anywhere outside of that dropdown, and I'd like to do that with Angular2 and with the Angular2 "approach"...</p>
  
  <p>I have implemented a solution, but I really do not feel confident with it. I think there must be an easiest way to achieve the same result, so if you have any ideas ... let's discuss :) !</p>
  
  <p>Here is my implementation:</p>
  
  <h1>The dropdown component:</h1>
  
  <p>This is the component for my dropdown:</p>
  
  <ul>
  <li>Every time this component it set to visible, (For example: when the user click on a button to display it) it subscribe to a "global" rxjs subject <em>userMenu</em> stored within the <em>SubjectsService</em>.</li>
  <li>And every time it is hidden, it unsubscribe to this subject.</li>
  <li>Every click anywhere <strong>within</strong> the template of this component trigger the <em>onClick()</em> method, which just stop event bubbling to the top (and the application component)</li>
  </ul>
  
  <p>Here is the code</p>
  
  <pre><code>export class UserMenuComponent {
  
      _isVisible: boolean = false;
      _subscriptions: Subscription&lt;any&gt; = null;
  
      constructor(public subjects: SubjectsService) {
      }
  
      onClick(event) {
          event.stopPropagation();
      }
  
      set isVisible(v) {
          if( v ){
              setTimeout( () =&gt; {
  this._subscriptions =  this.subjects.userMenu.subscribe((e) =&gt; {
                         this.isVisible = false;
                         })
              }, 0);
          } else {
              this._subscriptions.unsubscribe();
          }
          this._isVisible = v;
      }
  
      get isVisible() {
          return this._isVisible;
      }
  }
  </code></pre>
  
  <h1>The application component:</h1>
  
  <p>On the other hand, there is the application component (which is a parent of the dropdown component):</p>
  
  <ul>
  <li>This component catch every click event and emit on the same rxjs Subject (<em>userMenu</em>)</li>
  </ul>
  
  <p>Here is the code:</p>
  
  <pre><code>export class AppComponent {
  
      constructor( public subjects: SubjectsService) {
          document.addEventListener('click', () =&gt; this.onClick());
      }
      onClick( ) {
          this.subjects.userMenu.next({});
      }
  }
  </code></pre>
  
  <h1>What bother me:</h1>
  
  <ol>
  <li>I do not feel really comfortable with the idea of having a global Subject that act as the connector between those components.</li>
  <li>The <strong>setTimeout</strong>: This is needed because here is what happen otherwise if the user click on the button that show the dropdown:
  
  <ul>
  <li>The user click on the button (which is not a part of the dropdown component) to show the dropdown.</li>
  <li>The dropdown is displayed and <strong>it immediately subscribe to the userMenu subject</strong>.</li>
  <li>The click event bubble up to the app component and gets caught</li>
  <li>The application component emit an event on the <strong>userMenu</strong> subject</li>
  <li>The dropdown component catch this action on <strong>userMenu</strong> and hide the dropdown.</li>
  <li>At the end the dropdown is never displayed.</li>
  </ul></li>
  </ol>
  
  <p>This set timeout delay the subscription to the end of the current JavaScript code turn which solve the problem, but in a very in elegant way in my opinion.</p>
  
  <p>If you know cleaner, better, smarter, faster or stronger solutions, please let me know :) !</p>