Я хотел бы предупредить пользователей о несохраненных изменениях, прежде чем они покинут определенную страницу моего приложения angular 2. Обычно я бы использовал window.onbeforeunload
, но это не работает для одностраничных приложений.
Я обнаружил, что в angular 1 вы можете подключиться к $locationChangeStart
событию, чтобы создать confirm
поле для пользователя, но я не видел ничего, что показывало бы, как заставить это работать для angular 2, или если это событие все еще присутствует . Я также видел плагины для ag1, которые предоставляют функциональные возможности onbeforeunload
, но опять же, я не видел способа использовать его для ag2.
Я надеюсь, что кто-то еще нашел решение этой проблемы; любой метод подойдет для моих целей.
angular
angular2-routing
Whelch
источник
источник
Ответы:
Маршрутизатор обеспечивает обратный вызов жизненного цикла CanDeactivate
для более подробной информации см. руководство по охране
оригинал (роутер RC.x)
источник
canDeactivate
не получится.Чтобы также защитить защиту от обновлений браузера, закрытия окна и т. Д. (См. Комментарий @ ChristopheVidal к ответу Гюнтера для получения подробной информации по проблеме), я счел полезным добавить
@HostListener
декоратор в реализацию вашего классаcanDeactivate
для прослушиванияbeforeunload
window
события. При правильной настройке это защитит как от внутренней, так и от внешней навигации одновременно.Например:
Составная часть:
Охрана:
Маршруты:
Модуль:
ПРИМЕЧАНИЕ . Как указал @JasperRisseeuw, IE и Edge обрабатывают
beforeunload
событие иначе, чем другие браузеры, и будут включать словоfalse
в диалоговом окне подтверждения приbeforeunload
активации события (например, при обновлении браузера, закрытии окна и т. Д.). На переход в приложении Angular это не повлияет, и на него будет правильно отображаться назначенное вам предупреждающее сообщение. Те, кому нужна поддержка IE / Edge и не хотятfalse
показывать / хотят более подробное сообщение в диалоговом окне подтверждения приbeforeunload
активации события, могут также захотеть увидеть ответ @ JasperRisseeuw для обходного пути.источник
@Injectable()
в класс PendingChangesGuard. Кроме того, мне пришлось добавить PendingChangesGuard к своим провайдерам в@NgModule
import { HostListener } from '@angular/core';
beforeunload
. Если вы вернете Observable, это не сработает. Вы можете изменить свой интерфейс для чего - то , какcanDeactivate: (internalNavigation: true | undefined)
и вызвать ваш компонент , как это:return component.canDeactivate(true)
. Таким образом, вы можете проверить, не уходите ли вы изнутри, чтобы вернутьсяfalse
вместо Observable.Пример с @Hostlistener от stewdebaker работает очень хорошо, но я внес в него еще одно изменение, потому что IE и Edge отображают «false», возвращаемое методом canDeactivate () класса MyComponent конечному пользователю.
Составная часть:
источник
false
отображать в диалоговом окне подтверждения. Я немного отредактировал ваш ответ, включив его'$event'
в@HostListener
аннотацию, поскольку это требуется для доступа к нему вunloadNotification
функции.Я реализовал решение от @stewdebaker, которое работает очень хорошо, однако мне нужно было красивое всплывающее окно начальной загрузки вместо неуклюжего стандартного подтверждения JavaScript. Предполагая, что вы уже используете ngx-bootstrap, вы можете использовать решение @stwedebaker, но поменяйте «Guard» на тот, который я здесь показываю. Вам также необходимо представить
ngx-bootstrap/modal
и добавить новыйConfirmationComponent
:Охранник
(замените 'confirm' функцией, которая откроет модальное окно начальной загрузки - отображение нового, пользовательского
ConfirmationComponent
):confirm.component.html
confirm.component.ts
И поскольку новый
ConfirmationComponent
будет отображаться без использования aselector
в шаблоне html, его необходимо объявитьentryComponents
в вашем корнеapp.module.ts
(или как вы называете свой корневой модуль). Внесите следующие изменения вapp.module.ts
:app.module.ts
источник
Решение оказалось проще, чем ожидалось, не используйте,
href
потому что это не обрабатываетсяrouterLink
директивой использования Angular Routing .источник
Ответ за июнь 2020 г .:
Обратите внимание, что все решения, предложенные до этого момента, не устраняют существенный известный недостаток средств
canDeactivate
защиты Angular :Это обсуждалось здесь , здесь и подробно здесь
Пожалуйста, ознакомьтесь с моим решением проблемы, продемонстрированным здесь, которое безопасно позволяет обойти эту проблему *. Это было протестировано в Chrome, Firefox и Edge.
* ВАЖНОЕ ПРЕДУПРЕЖДЕНИЕ : на этом этапе вышеупомянутое очищает историю пересылки при нажатии кнопки «Назад», но сохраняет историю назад. Это решение не будет подходящим, если сохранение вашей будущей истории жизненно важно. В моем случае, когда дело доходит до форм , я обычно использую стратегию маршрутизации « главный-подробный» , поэтому ведение прямой истории не имеет значения.
источник