Вопрос или проблема
В Angular 18 я пытаюсь получить значение перед навигацией, но перенаправить на другую страницу на основе этого значения.
Пожалуйста, не ссылайтесь на страницу с заголовком “Redirecting Guards and Resolvers in Angular v18” Давиде Пассараро. Это не отвечает на мой вопрос.
Вот сценарий:
- Параметр пути передается в URL с именем key.
- Я использую этот ключ, чтобы получить значение (которое описывает произведение искусства) из бэкенда, на которое ссылается этот ключ.
- Если возвращается действительное значение, я хочу, чтобы это значение было связано с компонентом.
- Если вместо этого я получаю значение null, я хочу перенаправить на другую страницу, которая отображает сообщение 404 – не найдено.
Вот что у меня есть на данный момент:
const routes: Route = [
path: ":key",
component: ArtComponent,
resolve: {
art: () => inject(ArtService).get(key) // Это автоматически связывается с соответствующим свойством @Input() на компоненте
},
canActivate: [
() => {
const router = inject(Router);
*** как-то перенаправить на 404 страницу, если art равно null ***
return true;
}
]
];
Очевидно, мне чего-то не хватает. Альтернатива – выполнить перенаправление в функции ngOnInit() на компоненте ArtComponent, но это звучит некрасиво.
Ответ или решение
В Angular 18, для решения задачи перенаправления на основе результата разрешения данных перед загрузкой компонента, необходимо правильно настроить маршрутизацию и использовать механизм разрешителей (resolvers). Давайте разберем вашу ситуацию более подробно.
Общая структура маршрута
Ваша цель состоит в том, чтобы получить данные по ключу, переданному в URL, и на основе состояния этих данных перенаправить пользователя на страницу 404 в случае их отсутствия.
import { Route, Router, Resolve } from '@angular/router';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { ArtService } from './art.service';
import { ArtComponent } from './art.component';
@Injectable({ providedIn: 'root' })
export class ArtResolver implements Resolve<any> {
constructor(private artService: ArtService, private router: Router) {}
resolve(route: ActivatedRouteSnapshot): Observable<any> | Promise<any> | any {
const key = route.paramMap.get('key');
return this.artService.get(key).pipe(
tap(art => {
if (!art) {
this.router.navigate(['/404']); // Здесь происходит редирект на страницу 404
}
})
);
}
}
// Определяем маршруты
const routes: Route[] = [
{
path: ':key',
component: ArtComponent,
resolve: {
art: ArtResolver, // Используем наш разрешитель
}
},
{
path: '404',
component: NotFoundComponent // Компонент для страницы 404
}
];
Основные моменты
-
Создание сервиса разрешителя: Используйте сервис
ArtResolver
, который имплементирует интерфейсResolve
. В методеresolve
вы можете запрашивать данные уArtService
, передавая ключ из параметров маршрута. -
Обработка данных: За помощью оператора
tap
у вас есть возможность выполнить дополнительную логику после получения данных. Проверка на null и перенаправление происходит внутри этого оператора. -
Реализация маршрутов: Ваша конфигурация маршрутизации должна включать как маршрут для компонента
ArtComponent
, так и маршрут для страницы 404, куда будет происходить перенаправление.
Преимущества подхода
-
Чистота кода: Логика перенаправления находится в сервисе разрешителя, что делает ваш компонент менее загруженным и более сосредоточенным на представлении данных.
-
Избежание лишних проверок в компоненте: Вам не нужно заботиться о редиректе в методе
ngOnInit
, так как это уже обрабатывается на уровне маршрутизации.
Заключение
Использование механизма разрешителей в Angular предоставляет вам мощный инструмент для управления данными перед загрузкой компонентов. Ваша задача – позаботиться о том, чтобы данные были получены и проверены до того, как пользователь увидит компонент, что значительно улучшает пользовательский опыт. Настройка маршрутизации с использованием разрешителей делает ваше приложение более согласованным и предсказуемым.