enno.void
enno.void

Reputation: 6579

Angular pass resolve data to child-routes

i have the following Component Structure

So my routing looks like this:

const childroutes = [
  {
    path: '',
    children: [
      { path: 'edit', component: EditProjectComponent},
      { path: 'subres1', component: Subres1Component},
      { path: 'subres2', component: Subres2Component},
      { path: 'subres3', component: Subres3Component},
      { path: 'subres4', component: Subres4Component}
    ]
  }
]

{
    path: 'project/:projectId', 
    component: ProjectDetailComponent,
    children: childroutes,
    resolve: { project: ProjectResolver} /** resolve Project from ProjectService **/
}

As you can see i resolve my Projectdata from a service and can access them in ProjectDetailComponent via

this.route.snapshot.data

So now the question is, how can i pass the data resolved in "EditProjectComponent" to all its childroutes components?

I now that i could do the following to resolve project-data in childcomponents:

const childroutes = [
  {
    path: '',
    children: [
      { path: 'edit', component: EditProjectComponent,resolve: { project: ProjectResolver}},
      { path: 'subres1', component: Subres1Component,resolve: { project: ProjectResolver}},
      { path: 'subres2', component: Subres2Component,resolve: { project: ProjectResolver}},
      { path: 'subres3', component: Subres3Component,resolve: { project: ProjectResolver}},
      { path: 'subres4', component: Subres4Component,resolve: { project: ProjectResolver}}
    ]
  }
]

But this seems ugly and wrong.

Upvotes: 33

Views: 23645

Answers (3)

Pizzicato
Pizzicato

Reputation: 1621

Quite late response, but I think it's worth pointing this out: If routes change the parent reference might not work anymore. For a more flexible and resilient architecture you could use a service which would store the resolved data.

Resolver

@Injectable({ providedIn: 'root' })
export class ProjectResolver implements Resolve<Project> {
  constructor(
    private service: ProjectService,
    private store: StoreService,
  ) {}

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<Hero>|Promise<Hero>|Hero {
    return this.service.getProject(route.paramMap.get('id'))
      .pipe(tap(project => this.store.project = project));
  }
}

Then you can access this data anywhere you need it:

const projects = this.store.project;

Of course the store solution could be just a simple service with a class variable for projects, or something as complex as ngrx/store library.

Note: In case you don't find it proper to modify the state from the resolver code using something like tap, you could alter the state from the component that has that resolver, and access the state from the children components, or anywhere in the app where that data is needed.

Upvotes: 0

Pedro Santiago
Pedro Santiago

Reputation: 316

You just need to do this in child components:

ngOnInit() {
    this.route.parent.data
        .subscribe((data) => {
            this.edit = data.edit;
        });
}

Upvotes: 6

Desmond
Desmond

Reputation: 1552

You have two options here:

1. You can access parent resolve data via the child's resolver by creating a child-specific resolver and accessing the route's parent property.

[...module.ts | ...component.ts]

{
    path: 'project/:projectId', 
    component: ProjectDetailComponent,
    resolve: { project: ProjectResolver }
    children: [
        { 
            path: ':projectId/edit',
            component: EditProjectComponent,
            resolve: { edit: EditProjectResolve }
        }
    ]
}

edit-project-component.ts

ngOnInit() {
    this.edit = this.route.snapshot.data.edit;
}

2. You can bypass the child's resolver all together and access parent data from within the child component.

[...module.ts | ...component.ts]

{
    path: 'project/:projectId', 
    component: ProjectDetailComponent,
    resolve: { project: ProjectResolver }
    children: [
        { 
            path: ':projectId/edit',
            component: EditProjectComponent
        }
    ]
}

edit-project-component.ts

ngOnInit() {
    this.route.parent.data
        .subscribe((data) => {
            this.edit = data.edit;
        });
}

Upvotes: 54

Related Questions