Deerjon
Deerjon

Reputation: 59

How to get parameters before child component initialization

The usual scenario: User is presented with /login window. He logs in and get redirected to /dashboard, he may also load a list of other users at /users path. He then clicks on a user and ends up in /users/1 path. Selected users' data is now shown on the screen, as it was preloaded with the user list.

Parent component is "/users" Child path is ":userId"

Unusual, but possible scenario: User goes directly to /users/1 path by pasting the url (login token still valid, so he is not required to login).

At this point we do not have loaded user list, nor selected users' data.

I use path resolver to load the user list. It loads the list before the path is opened. The problem is with :userid child path. I can only get this parameter in child components constructor or Init methods.

This is not good, because each Component with child path has to extract that parameter and "select" the appropriate user from the list.

I want to have ability to select the user in a single place.

I have tried creating single resolver for each child path. This resolver tries to extract :userid parameter and then select it. I have also tried to assign that resolver to parent path only. I have also tried to create CanActivate guard, which should extract :userid.

None of these methods yield any result, because route[.snapshot].paramMap is empty.

I even tried to subscribe to paramMap of the route, but result is the same.

router file

{ path: '/users', component: parentComponent, children: [
        { path: ':userid', component: userComponent, resolve: { user: SelectUserResolver } }
        { path: ':userid/edit', component: userEditComponent, resolve: { user: SelectUserResolver } }
        { path: ':userid/show, component: userShowComponent, resolve: { user: SelectUserResolver } }
        ..... many more paths .....
    ]
}

resolver file

export class SelectUserResolver implement Resolve<any> {
    constructor(private userService: UserService, private route: ActivatedRoute) {}
    resolve() {
        let userId = this.route.snaphot.paramMap.get('userid'); //<- empty map
        this.userService.selectUser(userId);
    }
}

parentComponent

export class parentComponent {
    constructor(private route: ActivatedRoute) {
        let userId = this.route.snapshot.paramMap.get('userid'); //<- empty map
    }
}

userComponent

export class userComponent implements OnInit {
    constructor(private route: ActivatedRoute) {}
    ngOnInit() {
         let userId = this.route.snapshot.paramMap.get('userid');// <- this works.
    }
}

I expect paramMap to have userId, but it is empty no matter what i do. Accesing it inside child components is very bad, because i would need to repead this code for each component created.

Upvotes: 0

Views: 588

Answers (1)

penleychan
penleychan

Reputation: 5470

For resolvers you don't inject ActivatedRoute to your constructor. As per the documentation: https://angular.io/api/router/Resolve

When you implement Resolve<T> you can get the route from the method:

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<T> | Promise<T> | T

Upvotes: 1

Related Questions