Reputation: 47088
I have the router configured like this:
const routes: Routes = [
{
path: 'topic/:id',
component: TopicComponent,
resolve: { topic: TopicResolverService }
},
{
path: '',
pathMatch: 'full',
component: SummaryCardListComponent
}
]
And if I visit a topic directly like this:
http://localhost:4200/topic/concepts%2Fdemand%2Flead-time-demand
It redirects to the path http://localhost:4200/
.
What do we need to do to make the router render the link pasted into the browser?
The topic resolver service looks like this:
@Injectable({
providedIn: 'root'
})
export class TopicResolverService implements Resolve<Topic> {
constructor( private s: StateService ) { }
resolve(
route: ActivatedRouteSnapshot) {
const id = route.paramMap.get('id')
return this.s.loadingTopicStore$.pipe(
switchMap(()=>of(this.s.topicStore.findOneByID(id))
))
}
}
Upvotes: 2
Views: 849
Reputation: 1502
If I use decodeURIComponent('concepts%2Fdemand%2Flead-time-demand')
on your URI param, which is supposed to be an :id
, it resolves to concepts/demand/lead-time-demand
;
Now this baffles angular router, it searches for nested route like:
http://localhost:4200/topic/concepts/demand/lead-time-demand
This obviously does not exist, so it falls back to the base URL.
I had coded an Action
that merged Observable
events, and accidentally included the Observable
that triggers when the Topic
store loading was complete.
The action allowed the user to select a Slice of topics (Concepts
, Formulas
, Guides
...) and on
a select from the user it would navigate to ''
since that's the route that displays the slice.
Anyways since a paste of a URL into the browser that matches the route causes the application to load, this in turn causes the this.s.loadingTopicStore$
event to fire, and that caused the router to navigate to ''
.
For those interested this was the design of the action:
/**
* Note that are always only rendering
* `searchedTopics$` but we also
* track `selectedTopics$` because
* we search within this subset when
* it's selected.
*
* This also resets `topicStore.query`.
*/
onSelectTopicCategory() {
merge(
this.s.loadingTopicStore$,
this.s.activeTopicCategory$).
pipe(untilDestroyed(this)).subscribe(() => {
this.s.selectedTopics$ = combineLatest(
this.s.all$,
this.s.guides$,
this.s.blogs$,
this.s.concepts$,
this.s.formulas$,
this.s.tasks$,
this.s.activeTopicCategory$,
this.s.loadingTopicStore$,
this.onSelectTopicCategoryFunction)
this.s.searchedTopics$ = this.s.selectedTopics$
this.s.topicStore.query = ''
//We have to subscribe to this otherwise
//The combine latest function will never fire.
//The reason is that we are only using
//searchedTopics in the view, so we
//have to fire selectedTopics$ manually.
this.s.selectedTopics$.
pipe(untilDestroyed(this)).
subscribe()
})
}
And the function that is triggered by the merge
:
/**
* Observe the active topic category.
*
* Note that we navigate to '' when a category
* is selected such that we can see the selections
* rendered.
*/
onSelectTopicCategoryFunction(
all,
guides,
blogs,
concepts,
formulas,
tasks,
active,
loading) {
if (loading == false) {
// this.router.navigate([''])
switch (active) {
case TopicCategories.ALL:
return all
case TopicCategories.GUIDES:
return guides
case TopicCategories.BLOGS:
return blogs
case TopicCategories.CONCEPTS:
return concepts
case TopicCategories.FORMULAS:
return formulas
case TopicCategories.TASKS:
return tasks
default:
return all
}
}
else return []
}
It's implemented with @fireflysemantics/slice
:
https://www.npmjs.com/package/@fireflysemantics/slice
Upvotes: 1