У меня есть редуктор
on(CmsActions.loadCmsTopNewsSelected, (state, { slug }) => {
let selected;
if (state.data) {
selected = state.data.items.find(item => item.data.slug.iv === slug);
}
return {
...state,
selected
};
})
и этот охранник
canActivate(route: ActivatedRouteSnapshot): Observable<boolean | UrlTree> {
return this.checkStore().pipe(
switchMap(() => {
const slug = route.params.slug;
this.facade.selected(slug);
return this.facade.selected$.pipe(
map(selected => {
console.log('selected', selected);
if (selected) {
return true;
}
return this.router.parseUrl('/not-found');
})
);
}),
catchError(() => of(false))
);
}
checkStore(): Observable<boolean> {
return this.facade.loaded$.pipe(
tap(loaded => {
if (!loaded) {
this.facade.load(this.ITEMS_TO_LOAD);
}
}),
filter(loaded => {
console.log('loaded', loaded);
return loaded;
}),
take(1)
);
}
он отлично работает, если я иду по маршруту по ссылке маршрутизатора,
но если я пойду прямо, выбранный не определен, даже если
данные были загружены.
Что случилось?
ОБНОВИТЬ
Я публикую больше кода для лучшего понимания. Кстати, я жду загрузки данных, когда в браузере выполняется дочерний маршрут.
Родительские маршруты
{
path: 'news',
canLoad: [CmsNewsGuard],
loadChildren: () =>
import('./news/news.module').then(m => m.PublicNewsModule)
},
Дети
{
path: ':slug',
canActivate: [CmsNewsGuardSelected],
component: PublicNewsPageDetailsComponent
},
{
path: '',
component: PublicNewsListComponent,
pathMatch: 'full'
}
Фасад
export class CmsNewsFacade {
get data$(): Observable<CmsArray<CmsNews> | null> {
return this.store.pipe(select(selectCmsNewsData));
}
get error$(): Observable<Required<ErrorDto> | null> {
return this.store.pipe(select(selectCmsNewsError));
}
get loaded$(): Observable<boolean> {
return this.store.pipe(select(selectCmsNewsLoaded));
}
get selected$(): Observable<CmsNews | undefined> {
return this.store.pipe(select(selectCmsNewsSelected));
}
constructor(private store: Store<CmsState>) {}
load(top: number): void {
this.store.dispatch(CmsActions.loadCmsTopNews({ top }));
}
selected(slug: string): void {
this.store.dispatch(CmsActions.loadCmsTopNewsSelected({ slug }));
}
}
Селектор
export const selectCmsNewsSelected = createSelector(
selectMarketAccountFeature,
(state: CmsState) => {
return state.news.selected;
}
);
ОБНОВЛЕНИЕ2
Это работает с
return this.facade.selected$.pipe(
filter(selected => {
return !!selected;
}),
map(selected => {
if (selected) {
return true;
}
return this.router.parseUrl('/not-found');
})
);
но при этом я потерял цель показать не найденную страницу, если пул не существует :(
РАБОТАЕМ!
Я решил это, добавив проверку в редуктор
const current = state.data.items.find(item => item.data.slug.iv === slug);
if (!current) {
selected = null;
}
в карауле просто
filter(selected => {
return selected !== undefined;
}),
selectCmsNewsSelected
- person Anarno   schedule 31.01.2020