Guards¶
Guards
позволяют ограничить навигацию по определенным маршрутам. Например, если для доступа к определенному ресурсу требуется наличие аутентификации или наличие каких-то других условий, в зависимости от которых мы можем предоставить пользователю доступ, а можем и не предоставить. То есть guards защищают доступ к ресурсу, собственно поэтому данные элементы и названы так: "guards", что с английского можно перевести как "защитники".
CanActivate¶
CanActivate
представляет один из типов guards
, который позволяет управлять доступом к ресурсу при маршрутизации. Так, возьмем для примера базовый проект приложения:
Добавим в папку src/app
для примера пару компонентов. Первый компонент поместим в файл home.component.ts
:
1 2 3 4 5 6 7 |
|
И также добавим файл about.component.ts
:
1 2 3 4 5 6 7 |
|
Допустим, мы хотим ограничить доступ к компоненту AboutComponent
. Для этого добавим в папку src/app
новый файл about.guard.ts
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Класс AboutGuard
реализует интерфейс CanActivate
, а именно его метод canActivate()
. Этот метод получает два параметра — объекты ActivatedRouteSnapshot
и RouterStateSnapshot
, которые содержат информацию о запросе. ActivatedRouteSnapshot
позволяет получить различную информацию из запроса, в том числе параметры маршрута и строки запроса. Например, если бы в маршруте использовался параметр id
, то мы могли бы его здесь получить:
1 2 3 4 5 6 7 |
|
Результат метода — логическое значение, либо логическое значение, обернутое в объект Observable
. Если AboutGuard
разрешает переход, то метод canActivate()
должен возвращать true
. Если доступ запрещен, то метод возвращает false
.
Для тестирования обоих ситуаций здесь вызывается метод confirm()
, который отображает диалоговое окно с выбором. Если пользователь нажмет на кнопку отмены, то метод confirm
возвратит false
. Если же пользователь подтвердит действие, то будет возвращено значение true
.
Определим в файле app.component.ts
ссылки для перехода к компонентам:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
А в главном модуле приложения установим маршруты:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
|
Чтобы ограничить доступ по маршруту /about
, в определении этого маршрута прописывается параметр canActivate: [AboutGuard]
.
Кроме того, AboutGuard
должен быть указан в списке провайдеров модуля:
1 |
|
В итоге при попытке перехода по маршруту /about
, отобразится диалоговое окно с подтверждением перехода.
CanDeactivate¶
CanDeactivate
также позволяет управлять переходами. Он предназначен для таких, к примеру, случаев когда пользователь вводит какие-то данные. Однако не сохраняет их и покидает страницу. В этом случае мы могли бы выдать пользователю какое-либо предупреждение или окно с подтверждением перехода, чтобы избежать потери введенных данных.
То есть, если сравнивать с CanActivate
, CanActivate
проверяет возможность перехода на определенный компонент, а CanDeactivate
проверяет возможность ухода с определенного компонента.
Для примера добавим в папку src/app
новый файл exit.about.guard.ts
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
ExitAboutGuard
должен реализовать метод canDeactivate()
интерфейса CanDeactivate
. Этот метод собственно и управляет уходом с компонента и переходом на другой компонент.
Для управления навигацией в этот метод передается компонент, с которого осуществляется переход. Благодаря этому мы можем учитывать состояние компонента при переходе. Но передаваемый параметр должен реализовать определенный интерфейс — в данном случае ComponentCanDeactivate
. Выше определен этот интерфейс:
1 2 3 |
|
Название интерфейса не столь важно, главное, чтобы он определял метод canDeactivate()
, который возвращает объект boolean | Observable<boolean>
. Если нельзя осуществить переход, то возвращается значение false
, иначе возвращается значение true
. Это может быть просто логическое значение, либо же логическое значение, обернутое в объект Observable
.
Допустим, мы хотим управлять навигацией с компонента AboutComponent
. В этом случае класс AboutComponent
должен реализовать интерфейс ComponentCanDeactivate
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
Для имитации функционала в класс AboutComponent
добавлено свойство saved
, которое указывает, сохранены ли данные. С помощью метода save()
, который вызывается по нажатию на кнопку, мы можем управлять значением этой переменной. К примеру, нажали на кнопку, значит данные сохранены, и свойство saved
равно true
.
Далее в классе AboutComponent
реализуем метод canDeactivate()
. Этот метод и будет вызываться в ExitAboutGuard
. Поэтому в этом методе мы можем проверить состояние компонента и решить, стоит ли делать переход, надо ли выполнить какие-то дополнительные действия и т. д.
В данном случае, если this.saved == false
(то есть условно, если данные не сохранены), то выводим диалоговое окно для подтверждения действия.
Чтобы задействовать ExitAboutGuard
, изменим модуль AppModule
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|
Во-первых, в определении маршрута добавляется параметр
1 |
|
Во-вторых, сам класс ExitAboutGuard
добавляется в список провайдеров:
1 |
|
И теперь при попытки ухода с компонента AboutComponent
(если saved == false
), мы увидим диалоговое окно для подтверждения перехода: