Chciałbym zamknąć menu logowania, gdy użytkownik kliknie gdziekolwiek poza tym menu i chciałbym to zrobić z Angular2 i „podejściem” Angular2 ...
Wdrożyłem rozwiązanie, ale naprawdę nie czuję się z nim pewnie. Myślę, że musi być najłatwiejszy sposób na osiągnięcie tego samego rezultatu, więc jeśli masz jakieś pomysły ... porozmawiajmy :)!
Oto moja realizacja:
Składnik rozwijany:
To jest składnik mojego menu:
- Za każdym razem, gdy ten komponent jest ustawiony jako widoczny (na przykład: gdy użytkownik kliknie przycisk, aby go wyświetlić), subskrybuje „globalne” menu użytkownika tematu rxjs przechowywane w usłudze SubjectsService .
- I za każdym razem, gdy jest ukryty, wypisuje się z tego tematu.
- Każde kliknięcie w dowolnym miejscu w szablonie tego komponentu wyzwala metodę onClick () , która po prostu zatrzymuje bulgotanie zdarzeń na górę (i komponent aplikacji)
Oto kod
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;
}
}
Składnik aplikacji:
Z drugiej strony istnieje komponent aplikacji (który jest rodzicem komponentu rozwijanego):
- Ten komponent przechwytuje każde zdarzenie kliknięcia i emituje na tym samym temacie rxjs ( userMenu )
Oto kod:
export class AppComponent {
constructor( public subjects: SubjectsService) {
document.addEventListener('click', () => this.onClick());
}
onClick( ) {
this.subjects.userMenu.next({});
}
}
Co mi przeszkadza:
- Nie czuję się komfortowo z pomysłem posiadania globalnego podmiotu, który działa jako łącznik między tymi komponentami.
- SetTimeout : Jest to konieczne, ponieważ tutaj jest to, co się stało inaczej, gdy użytkownik kliknie na przycisk, który pokazuje listę rozwijaną:
- Użytkownik klika przycisk (który nie jest częścią rozwijanego komponentu), aby wyświetlić listę rozwijaną.
- Zostanie wyświetlone menu rozwijane, które natychmiast zasubskrybuje temat menu użytkownika .
- Zdarzenie kliknięcia pojawia się w dymku do komponentu aplikacji i zostaje złapane
- Komponent aplikacji emituje zdarzenie w temacie userMenu
- Komponent listy rozwijanej przechwytuje tę akcję w userMenu i ukrywa listę rozwijaną.
- Na końcu lista rozwijana nigdy nie jest wyświetlana.
Ten ustawiony limit czasu opóźnia subskrypcję do końca bieżącej tury kodu JavaScript, co rozwiązuje problem, ale moim zdaniem w bardzo elegancki sposób.
Jeśli znasz czystsze, lepsze, mądrzejsze, szybsze lub mocniejsze rozwiązania, daj mi znać :)!