¿Cómo puedo cerrar un menú desplegable al hacer clic afuera?

Me gustaría cerrar mi menú desplegable de inicio de sesión cuando el usuario haga clic en cualquier lugar fuera de ese menú desplegable, y me gustaría hacerlo con Angular2 y con el "enfoque" de Angular2 ...

He implementado una solución, pero realmente no me siento seguro con ella. Creo que debe haber una manera más fácil de lograr el mismo resultado, así que si tienes alguna idea ... ¡discutamos :)!

Aquí está mi implementación:

El componente desplegable:

Este es el componente para mi menú desplegable:

Cada vez que este componente se configura como visible, (por ejemplo: cuando el usuario hace clic en un botón para mostrarlo) se suscribe a un asunto rxjs "global"Menú del Usuario almacenado dentro deSujetos Servicio.Y cada vez que está oculto, se da de baja de este tema.Cada clic en cualquier lugardentro la plantilla de este componente activa elal hacer clic() método, que simplemente detiene el burbujeo de eventos en la parte superior (y el componente de la aplicación)

Aqui esta el codigo

export class UserMenuComponent {

    _isVisible: boolean = false;
    _subscriptions: Subscription<any> = null;

    constructor(public subjects: SubjectsService) {
    }

    onClick(event) {
        event.stopPropagation();
    }

    set isVisible(v) {
        if( v ){
            setTimeout( () => {
this._subscriptions =  this.subjects.userMenu.subscribe((e) => {
                       this.isVisible = false;
                       })
            }, 0);
        } else {
            this._subscriptions.unsubscribe();
        }
        this._isVisible = v;
    }

    get isVisible() {
        return this._isVisible;
    }
}
El componente de la aplicación:

Por otro lado, está el componente de la aplicación (que es un padre del componente desplegable):

Este componente captura cada evento de clic y emite en el mismo Asunto rxjs (Menú del Usuario)

Aquí está el código:

export class AppComponent {

    constructor( public subjects: SubjectsService) {
        document.addEventListener('click', () => this.onClick());
    }
    onClick( ) {
        this.subjects.userMenu.next({});
    }
}
Lo que me molesta:No me siento realmente cómodo con la idea de tener un Sujeto global que actúe como conector entre esos componentes.lossetTimeout: Esto es necesario porque esto es lo que sucederá si el usuario hace clic en el botón que muestra el menú desplegable:El usuario hace clic en el botón (que no es parte del componente desplegable) para mostrar el menú desplegable.Se muestra el menú desplegable yse suscribe inmediatamente al sujeto del menú de usuario.El evento de clic aparece en el componente de la aplicación y queda atrapadoEl componente de aplicación emite un evento en elMenú del Usuario temaEl componente desplegable captura esta acción enMenú del Usuario y esconder el menú desplegable.Al final, el menú desplegable nunca se muestra.

Este tiempo de espera establecido retrasa la suscripción al final del turno actual del código JavaScript que resuelve el problema, pero en una forma muy elegante en mi opinión.

Si conoce soluciones más limpias, mejores, más inteligentes, más rápidas o más fuertes, ¡hágamelo saber :)!

Respuestas a la pregunta(18)

Su respuesta a la pregunta