When do you use React-Router getChildRoutes? - javascript

I'm confused about how and when you can use getChildRoutes because it's part of PlainRoute. How do you access PlainRoute in the first place? So instead of building <Route> components I can use <PlainRoute>s and then inside the component it was rendering it will have getChildRoutes? What does partialNextState refer to?

Plain routes are ordinary JavaScript objects, and can be used in <Router> like so:
const routes = {
path: '/',
component: App,
indexRoute: {
component: Home,
},
childRoutes: [
{ path: 'page1', component: Page1 },
{
path: 'page2',
component: SomeWrapper,
childRoutes: [
{ path: 'subpage1', component: Subpage1 },
],
},
],
};
ReactDOM.render(<Router history={ browserHistory } routes={ routes }/>, document.body);
That is, the indexRoute - if present - corresponds to adding an <IndexRoute> as a child of a <Route>, and childRoutes corresponds to adding child <Route>s. They both accept the same attributes as the corresponding JSX tags accept props.
Plain routes are useful for example for splitting your route definition up in multiple files. In a large app, it may be useful to decouple pages from their exact location in the route hierarchy, and build the route hierarchy up by importing childRoutes to immediate parent modules instead of having the entire route hierarchy hardcoded into the root module. It is also easy to build reusable navigation components like tab containers and breadcrumbs if you use plain routes, as the routes themselves can then be sent as props defining the links those components should include.
getChildRoutes and getIndexRoute are asynchronous variants of the childRoutes and indexRoute attributes, and allow for dynamic routing and code splitting. For example, you could for fun make getChildRoutes refer to itself recursively. I don't know what partialNextState is supposed to be, and I've never needed to use it.

Related

Angular component reloads when navigating

Routes for my Module:
const routes: Routes = [
{ path: ":level1/:level2/:level3", component: CategoriesComponent },
{ path: ":level1/:level2", component: CategoriesComponent},
{ path: ":level1", component: CategoriesComponent},
{ path: "", component: CategoriesComponent },
];
the Categories component Generates some links like so:
<a [routerLink]="['category1']" [relativeTo]="activatedRoute">My Link</a>
the ngOnInit & ngOnDestroy are called each time it navigates between those routes.
What I need is the component to stay mounted and not re-init each time.
Stackblitz link to illustrate the difference between using QueryParameters and RouteParameters: Angular example
NOTE: Dont suggest RouteReuseStrategy: that isn't the answer we are looking for. I have another angular application that doesn't reload the component between routes. And this is the official expected behaviour.
You need to dive into a RouteReuseStrategy and create your custom strategy with saving touched pages
Docs
RouteReuseStrategy allows you to tell Angular not to destroy a component, but in fact to save it for re-rendering at a later date. https://stackoverflow.com/a/41515648/15439733

Multiple named router-outlet - component imported but not initialized and rendered

I'm using multiple named angular 8 router-outlet in a web app. All the routerLink seems to work as it changes the URL but components in my 2nd router-outlet are imported but not initialized nor rendered.
I made a Stackblitz available here : https://stackblitz.com/edit/ng-multiple-router-outlet?file=src/app/app.component.ts
As you can see, when you click on the sidebar, under photos you have a second navigation level by clicking on Google or Facebook but nothing is rendered.
In modules, components used in other modules and RouterModule are well exported to be accessible, I don't see what I've done wrong.
I tried to declare the routes with both forRoot and forChild methods, I put some logs, but I'm running out of clues.
Thanks for your help !
Angular router is pretty simple once you understand how nested routes works there.
Let's imagine a simple configuration:
RouterModule.forRoot([
{
path: '',
component: HomeComponent,
children: [
{ path: 'child', component: ChildComponent }
]
}
])
How would you use router-outlet to cover all routes above?
app.component.html
\
contains
\
<router-outlet></router-outlet>
\/
renders
\
HomeComponent
home.component.html
\
contains
\
<router-outlet></router-outlet>
renders
\
ChildComponent
The main takeaway here is that router-outlet renders component depending on router context. Once it renders component a new context is created and all router-outlet's declared at this level will look at children configuration.
The same is true for named routes.
You've generated the link like:
(selection:facebook//sidebar:photos)
It means that these named routes should be at the same root level. But you defined <router-outlet name="selection"></router-outlet> at nested level inside rendered by router LibraryComponent.
Let's add this outlet at the same level as 'sidebar':
<router-outlet name="sidebar"></router-outlet>
<router-outlet name="selection"></router-outlet>
and it actually works stackblitz
Now let's come back to your attempt. If you want to render selection components inside selection.component.html then you should be using nested named routed links:
selection.component.html
[routerLink]="['.', { outlets: { selection: [routeName] } }]"
\/
relative path
The above binding will generate nested links like (sidebar:photos/(selection:facebook))
Now you need to move SelectionRoutes configuration to children property of photos path:
selection.module.ts
imports: [
CommonModule,
RouterModule, //.forChild(SelectionRoutes)
],
sidebar.routes.ts
import { SelectionRoutes } from '../selection/selection.routes';
...
export const SidebarRoutes: Route[] = [
{ path: 'photos', component: LibraryComponent, outlet: 'sidebar', children: SelectionRoutes },
Stackblitz Example
Update
In order to make facebook as a default subroute you create a route with redirectTo option like:
export const SelectionRoutes: Route[] = [
{ path: 'facebook', component: FacebookComponent, outlet: 'selection' },
{ path: 'google', component: GoogleComponent, outlet: 'selection' },
{ path: '', redirectTo: '/(sidebar:photos/(selection:facebook))', pathMatch: 'full', },
]
Stackblitz Example

Angular feature routing module - Child component not loaded

I have a feature module that I load in the AppModule, the AppRoutingModule looks like
const appRoutes: Routes = [
...
{
path: 'move-request/:id',
loadChildren: 'app/modules/move_requests/move_requests.module#MoveRequestModule'
},
...
];
And the configuration of routing for the feature module looks like
const moveRequestRoutes: Routes = [
{
path: '',
component: MoveRequestFormComponent,
data: {title: 'Move Request'}
},
{
path: 'move-request-success',
component: RequestSuccessComponent,
data: {title: 'Move request success'}
},
];
I would like to navigate to MoveRequestFormComponent as the default component when move-request/:id is routed to, this works fine, but when I call
this.router.navigate(['/move-request-success', {}]);
In MoveRequestFormComponent after some response from the server, I get
zone.js:665 Unhandled Promise rejection: Cannot match any routes. URL Segment: 'move-request-success' ; Zone: <root> ;
This configuration was working before I switched to Angular 6, Is it because of the change in the AppModule, where I have excluded this feature module as an import?
Any assistance on what I am missing would be much appreciated. As I have also tried with having a third component which will be the default component and uses the router-outlet to render the children and have a children property on this route to have as children
{
path: '',
component: MoveRequestFormComponent,
data: {title: 'Move Request'}
},
{
path: 'move-request-success',
component: RequestSuccessComponent,
data: {title: 'Move request success'}
},
But that also did not work, it stayed on the MoveRequestFormComponent, when 'move-request-success' was navigated to.Or maybe I should change the approach?
You don't have to import the feature module in AppModule as it is lazily-loaded. When you navigate to move-request/:id/move-request-success, the path matches the default route with path:'', and then it will look for and children of that route. You should add pathMatch:'full' to the first route, which is the default in this case. Since the mentioned route matches the first route and is unable to find and match any children, it is showing the error.
this.router.navigate(['/move-request-success', {}]);. If you add a / to a route this means you use absolute path from root. Have you tried without / ?
EDIT:
I think I see your problem. You navigate to a module with multiple components, which means after lazy loading the router configuration from the loaded module is used. This means
move-request/:id
Is the root of your module and every subroute needs to include the modules root in the url:
Your route should be move-request/:id/move-request-success
Urls in lazy loaded modules are:
module root (in your case move-request/:id) + configured route of the specific component (in your case move-request-success)

Vue router-link: sibling or child relative links

I'm working on a web application using Vue 2 as the framework and the accompanying Vue Router for routing purposes.
I'm developing a kind of tabbed view, so my current approach is to define child routes for my main component. Something along the lines of:
{ path: '/user/:id', component: User, children: [
{ path: '', component: UserHome },
{ path: 'profile', component: UserProfile },
{ path: 'posts', component: UserPosts }
]}
The setup is OK and routing works as expected. I'm now looking into defining links from the User component's template to its children (the tabbed navigation). I'm also looking to define a link from the UserHome component directly to its sibling components (UserProfile& UserDetails).
As far as I can tell there's no easy way to avoid repeating the full path in the toattribute of the router-link component to avoid breaking the navigation, see this working Fiddle & this broken Fiddle and notice the values of the to attributes. I would expect to be able to define a relative path as the value of the to attribute to navigate between child and/or sibling paths.
Does anyone know if there's a better way to avoid repeating full navigation paths in a router-link component?

Main app component not able to get params

I have a scenario where the first segment in the url will be a unique identifier. That unique identifier will be used in main routes and in the child routes as well.
Here is how i have defined my routes config
export const routes:RouterConfig = [{
path: ':academy_url',
children: [
{path: '', component: CoursesComponent},
{path: 'courses',
children: [
{path: '', component: CoursesComponent}
]
}
}
];
:academy_url is the param i plan on using in the child components. I can access this param in the child components (CoursesComponent for example), but i do not have for some reason access to it in the main app component.
The params array is empty in the main component when i try observables as well as snapshot.How do i access this param in app component? Right now i have a workaround which depends on a service emitting the param value from child components, but that is very inconvenient as this happens every time a component loads or page refreshed.
I need a more direct approach and i feel that it's either a bug or maybe the main app component is not supposed to have access to entry level params?
Also, i tried to create a plunker but i'm not sure how i make it work in there as it gives me undefined route error for it's plunker url key.

Categories

Resources