Search code examples
angularlazy-loadingangular-routingangular-moduleangular-router

Angular router: how to pass data to lazy loading module?


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?


Solution

  • 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