Guards¶
Route Guards позволяют ограничить доступ к маршрутам на основе определенного условия, например, только авторизованные пользователи с определенным набором прав могут просматривать страницу.
Также можно перед переходом на другой URL предупредить пользователя, что все его несохраненные изменения на текущей странице будут потеряны.
Различают следующие виды guard-ов:
CanActivate
— разрешает/запрещает доступ к маршруту;CanActivateChild
-разрешает/запрещает доступ к дочернему маршруту;CanDeactivate
— разрешает/запрещает уход с текущего маршрута;Resolve
— выполняет какое-либо действие перед переходом на маршрут, обычно ожидает данные от сервера;CanLoad
— разрешает/запрещает загрузку модуля, загружаемого асинхронно.
Все guard-ы должны возвращать либо true
, либо false
. И происходить это может как в синхронном режиме (тип Boolean
), так и в асинхронном режиме (Observable<boolean>
или Promise<boolean>
).
Если будет возвращено false
, будет инициировано событие маршрутизации NavigationCancel
.
У одного URL может быть одновременно несколько guard-ов, причем одного и того же типа. Все guard-ы — обычные классы, реализующие определенный интерфейс. Указываются они в виде массива значением одноименных свойств при определении маршрутов.
Сначала выполняются CanDeactivate
и CanActivateChild
, затем — CanActivate
. CanLoad
будет вызван только в случае асинхронной загрузки модуля.
Guard-ы импортируются в модуль, к которому относится модуль маршрутизации, и перечисляются в блоке providers
.
auth.guard.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
app-routing.module.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
app.module.ts
1 |
|
В AuthGuard
реализуется интерфейс CanActivate
и CanActivateChild
(создаваемый класс обязательно должен содержать определение метода CanActivate
и CanActivateChild
соответственно).
Присутствие CanActivateChild
говорит о том, что метод будет вызываться при каждом переходе на дочерний URL независимо от уровня иерархии. Часто оба метода выполняют одну и ту же проверку, и CanActivateChild
нужен в этом случае для того, чтобы указать его у самого верхнего маршрута.
В приведенном примере предполагается, что при авторизации пользователя значение свойства isLoggedIn
сервиса AuthService
устанавливается в true
.
После того, как пользователь попал на маршрут, можно предотвратить с него уход используя CanDeactivate
guard-а. Например, можно попросить пользователя подтвердить уход со страницы, чтобы предотвратить потерю несохраненных данных или других внесенных изменений.
can-deactivate.guard.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
app-routing.module.ts
1 2 3 |
|
В отличие от CanActivate
CanDeactivate
имеет дополнительно еще один параметр component
, который содержит экземпляр указанного компонента, в нашем случае это BuyTicketFormComponent
.
Если пользователь изменил какие-то данные и не сохранил их, то DataChangesGuard
перед сменой маршрута уведомит об этом пользователя и запросит подтверждение смены URL.
Если в приложении нескольким маршрутам необходим один и тот же CanDeactivate
guard, то во избежание создания guard-а для каждого из компонентов, можно создать интерфейс и указывать его вместо компонента при создании guard-а.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
При обращении приложения к удаленному API, отображение данных происходит с некоторой задержкой, во время которой интерфейс может оказаться "сломанным", что сразу негативно скажется на общем впечатлении.
Для решения этой проблемы можно было бы использовать CanActivate
, но концептуально он предназначен для других целей. А здесь понадобится resolver
.
Resolver — это сервис, реализующий интерфейс Resolve
, а именно метод resolve()
, который обязательно должен возвращать данные типа Observable
. Указанный для любого маршрута, Resolver
разрешает переход на него после выполнения Observable
в resolve()
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
Выполнение метода resolve()
(как синхронного, так и асинхронного) инициирует событие NavigationEnd
, что можно использовать для скрытия прелоадера при переходах между страницами.