Chciałbym ostrzec użytkowników o niezapisanych zmianach, zanim opuszczą określoną stronę mojej aplikacji Angular 2. Zwykle bym używał window.onbeforeunload
, ale to nie działa w przypadku aplikacji jednostronicowych.
Odkryłem, że w angular 1 możesz podłączyć się do $locationChangeStart
zdarzenia, aby rzucić confirm
pudełko dla użytkownika, ale nie widziałem niczego, co pokazuje, jak to działa dla angular 2, lub jeśli to zdarzenie jest nadal obecne . Widziałem również wtyczki dla ag1, które zapewniają funkcjonalność dla onbeforeunload
, ale znowu nie widziałem sposobu, aby użyć go dla ag2.
Mam nadzieję, że ktoś inny znalazł rozwiązanie tego problemu; każda metoda będzie dobrze działać dla moich celów.
angular
angular2-routing
Whelch
źródło
źródło
Odpowiedzi:
Router zapewnia funkcję zwrotną dotyczącą cyklu życia CanDeactivate
więcej szczegółów znajdziesz w samouczku strażników
oryginalny (router RC.x)
źródło
canDeactivate
, nie będzie działać.Aby zabezpieczyć się przed odświeżeniem przeglądarki, zamknięciem okna itp. (Zobacz komentarz @ ChristopheVidal do odpowiedzi Güntera, aby uzyskać szczegółowe informacje na temat tego problemu), uważam, że pomocne jest dodanie
@HostListener
dekoratora docanDeactivate
implementacji klasy, aby nasłuchiwaćbeforeunload
window
wydarzenia. Po prawidłowym skonfigurowaniu chroni to jednocześnie przed nawigacją w aplikacji i zewnętrzną.Na przykład:
Składnik:
Strzec:
Trasy:
Moduł:
UWAGA : Jak zauważył @JasperRisseeuw, IE i Edge obsługują
beforeunload
zdarzenie inaczej niż inne przeglądarki i dołączają słowofalse
w oknie dialogowym potwierdzenia, gdybeforeunload
zdarzenie się aktywuje (np. Przeglądarka odświeża się, zamyka okno itp.). Nawigacja w aplikacji Angular nie ma wpływu i prawidłowo wyświetla wyznaczony komunikat ostrzegawczy z potwierdzeniem. Ci, którzy muszą obsługiwać IE / Edge i nie chcąfalse
pokazywać / chcą bardziej szczegółowego komunikatu w oknie dialogowym potwierdzenia, gdybeforeunload
zdarzenie się aktywuje, mogą również chcieć zobaczyć odpowiedź @ JasperRisseeuw na obejście.źródło
@Injectable()
do klasy PendingChangesGuard. Ponadto musiałem dodać PendingChangesGuard do moich dostawców w@NgModule
import { HostListener } from '@angular/core';
beforeunload
. Jeśli zwrócisz Observable, to nie zadziała. Możesz zmienić interfejs na coś takiegocanDeactivate: (internalNavigation: true | undefined)
i zadzwonić do komponentu tak:return component.canDeactivate(true)
. W ten sposób możesz sprawdzić, czy nie oddalasz się wewnętrznie, aby powrócićfalse
zamiast Obserwowalnego.Przykład z @Hostlistener ze stewdebaker działa naprawdę dobrze, ale wprowadziłem jeszcze jedną zmianę, ponieważ IE i Edge wyświetlają "false", które jest zwracane przez metodę canDeactivate () w klasie MyComponent do użytkownika końcowego.
Składnik:
źródło
false
aby pojawiały się w oknie dialogowym potwierdzenia. Dokonałem niewielkiej zmiany w Twojej odpowiedzi, aby dołączyć adnotację'$event'
do@HostListener
adnotacji, ponieważ jest to wymagane, aby mieć do niej dostęp wunloadNotification
funkcji.Zaimplementowałem rozwiązanie z @stewdebaker, które działa naprawdę dobrze, jednak chciałem mieć ładne okienko bootstrap zamiast niezgrabnego standardowego potwierdzenia JavaScript. Zakładając, że używasz już ngx-bootstrap, możesz użyć rozwiązania @ stwedebaker, ale zamień „Guard” na ten, który tutaj pokazuję. Musisz także wprowadzić
ngx-bootstrap/modal
i dodać noweConfirmationComponent
:Strzec
(zamień 'confirm' na funkcję, która otworzy modal bootstrap - wyświetlając nowy, niestandardowy
ConfirmationComponent
):potwierdzenie.component.html
potwierdzenie.component.ts
A ponieważ nowy
ConfirmationComponent
będzie wyświetlany bez użycia aselector
w szablonie html, musi być zadeklarowany wentryComponents
katalogu głównymapp.module.ts
(lub jakkolwiek nazwiesz swój moduł główny). Wprowadź następujące zmiany wapp.module.ts
:app.module.ts
źródło
Rozwiązanie było łatwiejsze niż oczekiwano, nie używaj,
href
ponieważ nie jest to obsługiwane przezrouterLink
dyrektywę użycia kątowego routingu .źródło
Odpowiedź z czerwca 2020 r .:
Zwróć uwagę, że wszystkie proponowane do tej pory rozwiązania nie rozwiązują problemu z istotną znaną wadą
canDeactivate
osłon Angulara:Zostało to omówione tutaj , tutaj i szczegółowo tutaj
Zobacz moje rozwiązanie problemu , które zostało tutaj przedstawione, które bezpiecznie rozwiązuje ten problem *. Zostało to przetestowane w Chrome, Firefox i Edge.
* WAŻNE OSTRZEŻENIE : na tym etapie powyższe wyczyści historię do przodu po kliknięciu przycisku Wstecz, ale zachowa historię wstecz. To rozwiązanie nie będzie odpowiednie, jeśli zachowanie historii do przodu jest niezbędne. W moim przypadku, jeśli chodzi o formularze, zazwyczaj używam strategii routingu typu master-detail , więc utrzymywanie historii przekazywania nie jest ważne.
źródło