Gostaria de fechar meu menu suspenso de login quando o usuário clicar em qualquer lugar fora desse menu suspenso e gostaria de fazer isso com o Angular2 e com a "abordagem" do Angular2 ...
Eu implementei uma solução, mas realmente não me sinto confiante com ela. Eu acho que deve haver uma maneira mais fácil de obter o mesmo resultado, então se você tiver alguma idéia ... vamos discutir :)!
Aqui está a minha implementação:
O componente suspenso:
Este é o componente para o meu menu suspenso:
- Toda vez que este componente que definir a visível, (Por exemplo: quando o usuário clique em um botão para exibi-lo) que assinar um assunto "global" rxjs usermenu armazenado dentro do SubjectsService .
- E toda vez que está oculto, cancela a inscrição neste assunto.
- Cada qualquer clique dentro do modelo deste gatilho componente do onClick () método, que apenas parada evento bolha ao topo (e o componente de aplicação)
Aqui está o código
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;
}
}
O componente do aplicativo:
Por outro lado, existe o componente de aplicativo (que é o pai do componente suspenso):
- Esse componente captura todos os eventos de clique e emite no mesmo assunto rxjs ( userMenu )
Aqui está o código:
export class AppComponent {
constructor( public subjects: SubjectsService) {
document.addEventListener('click', () => this.onClick());
}
onClick( ) {
this.subjects.userMenu.next({});
}
}
O que me incomoda:
- Não me sinto muito à vontade com a ideia de ter um Assunto global que atue como o conector entre esses componentes.
- O setTimeout : Isso é necessário, porque é o que acontece caso contrário, se o usuário clicar no botão que mostra o menu suspenso:
- O usuário clica no botão (que não faz parte do componente suspenso) para mostrar o menu suspenso.
- O menu suspenso é exibido e ele se inscreve imediatamente no assunto userMenu .
- O evento click clica no componente do aplicativo e é capturado
- O componente de aplicativo emite um evento no assunto userMenu
- O componente suspenso captura essa ação no userMenu e oculta o menu suspenso.
- No final, o menu suspenso nunca é exibido.
Esse tempo limite definido atrasa a assinatura até o final do código JavaScript atual, que resolve o problema, mas de uma maneira muito elegante na minha opinião.
Se você souber soluções mais limpas, melhores, mais inteligentes, mais rápidas ou mais fortes, entre em contato :)!