I have the following routing paths for a module of my Angular app:
@NgModule({
imports: [
RouterModule.forChild([
{
path: 'documents',
data: { myObject: MyConstants.OPTION_ONE },
children: [
{
path: ':ID_DOC',
children: [
{ path: 'edit', component: EditDocumentComponent },
{ path: '', component: DocumentDetailsComponent },
]
},
{ path: 'add', component: AddDocumentComponent },
{ path: '', component: DocumentsListComponent }
]
}
])
],
exports: [
RouterModule
]
})
export class DocumentsManagementRoutingModule {
}
As you can see I use data
property to pass some data to every path in "documents", so I can get it from any of the Components declared in the routing paths:
For example here is how I get data in DocumentDetailsComponent
:
export class DocumentDetailsComponent implements OnDestroy {
private obsData: Subscription;
private option: any;
constructor(private route: ActivatedRoute) {
this.obsData = this.route.data.subscribe(data => {
this.option = data['myObject'];
});
}
ngOnDestroy(): void {
this.obsData.unsubscribe();
}
}
Now I changed the routing structure of the entire app and I call the above module from other modules, in lazy loading, using loadChildren
attribute. And I pass data in the same way:
@NgModule({
imports: [
RouterModule.forChild([
{
path: 'users',
loadChildren: 'app/documents/documents.module#DocumentsModule',
data: { myObject: MyConstants.OPTION_ONE }},
{
path: ':ID_USER',
children: [
{ path: 'edit', component: EditUserComponent },
{ path: '', component: UserDetailsComponent },
]
},
{ path: 'add', component: AddUserComponent },
{ path: '', component: UserListComponent }
])
],
exports: [
RouterModule
]
})
export class UsersManagementRoutingModule {
}
And I did the same for all the other modules that calls DocumentsManagementRoutingModule
, changing myObject
property to MyConstants.OPTION_TWO
, MyConstants.OPTION_THREE
and so on, according to my needs.
Then, since I don't know the module and its related path that calls my lazy loading module, how to get data
property from the caller module?
There are various ways by which we can pass data from one component to another. Angular 7.2. 0 introduced a new way to pass data using State Object while navigating between routed components.
A function that returns a set of routes to load.
I think I may understand what's the question is asking about.
Here is the routing graph of the plunker @smartmouse provided.
- home
- shop
- contact
- map
- about
There is a data
object configured on the home
route config. The direct child routes can access this data object. The problem is, the non-direct child map
wants to access the data
object, but apparently, it can't.
And we can know @smartmouse wants push that even further -- nested non-direct child routes can access data from ancestor.
See the plunker I've modified. https://plnkr.co/edit/FA7mGmspUXHhU8YvgDpT
You can see that I define a extra child component DefaultComponent
for contact
. It shows that it is the direct and default child of route contact
, which can be interpreted as it is also the direct child of superior route home
. So, it can access the data
object.
Look at the plunker provided by me again.
NOTE: The Angular packages I'm using is v4.3.0
I define some query params in home.component.ts
for contact
route. You can see how to use it.
Pros:
Cons:
you can't define query params in route config.
But you can use some route lifecycle hooks to define them for target ancestor routes
Define a data share service on top level of the application playing as Singleton Pattern. Also, use some util to prevent it from being initiated twice. Then you can put some data in it, and retrieve it anywhere.
Pros:
Cons:
Someone may find out I've also defined resolve
sample code in the plunker. It's to show it has the same behavior like data
in route config, except it actually is for dynamic data retrieving.
https://vsavkin.com/angular-router-understanding-router-state-7b5b95a12eab#5400
The data property is used for passing a fixed object to an activated route. It does not change throughout the lifetime of the application. The resolve property is used for dynamic data.
Take @smartmouse's plunkr as example.
We have data
defined in 'home' route config. We can define a data resolver in ContactModule
for contact's default route, and proxy the data passed from superior route. Then all its direct child routes can access the resolved data object.
Pros:
Cons:
There is no perfect and universal solution, for now, with common usage of Angular. Someone should weigh the pros and cons and choose the proper one.
You can traverse the parent routes by using activatedRoute.pathFromRoot, and get the data from the nearest ancestor that has it available. Something like this seems to work:
ngOnInit(): void {
let idx = this.activatedRoute.pathFromRoot.length - 1;
while(this.sharedData == null && idx > 0){
this.sub = this.activatedRoute.pathFromRoot[idx].data.subscribe(subData => {
if(subData.id)
this.sharedData = subData;
console.log('shared data', this.sharedData);
});
idx--;
}
}
https://plnkr.co/edit/K5Rb1ZvTvSQNM6tOLeFp
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With