13

Lets say we have a component in Aurelia named UserRouter, which is a child router and handles routing to UserProfile, UserImages and UserFriends.

I want the UserRouter to load in the user from the API (on canActivate) and then pass this this user data to sub components.

Loading in the data is fine, how do I pass it down to sub components so they can all read it? e.g. placing an attribute on <router-view>.

I've tried the bindingContext argument on the bind() method of sub components but this hasn't worked.

Thanks

Mike
  • 7,244
  • 5
  • 21
  • 27

5 Answers5

6

The way I did this, was by adding additional information to the child router definition eg:

configureRouter(config, router){
   config.map([
  { route: [''], name: 'empty', moduleId: './empty', nav: false, msg:"choose application from the left" },
  { route: 'ApplicationDetail/:id',  name: 'applicationDetail',   moduleId: './applicationDetail', nav: false, getPickLists : () => { return this.getPickLists()}, notifyHandler : ()=>{return this.updateHandler()} }
]);

in the first route from this example, I pass in a text message by adding my own porperty 'msg' to the route object. in the second route I pass in some event handlers, but could have been some custom objects or antything else.

In the childmodel I receive these additional elements in the activate() method:

export class empty{
  message;

  activate(params, routeconfig){
    this.message=routeconfig.msg || "";
  }
}

I guess in your case, you would add the user object to the child router definition.

  • 1
    in this case, how can we make getPickLists two way bindable, I mean anything changed in picklist inside child route can be reflected in parent as well? – Manoj Shevate Dec 07 '16 at 07:18
3

You could bind the router/user object to the <router-view>

<router-view router.bind="router"></router-view>

I have the same issue, so I'd love to see what you come up with!!

Moose
  • 152
  • 1
  • 11
2

You could use the event aggregator to publish out an event with the data and the sub components could subscribe and listen for that event. This would avoid coupling between them. However, there may be a downside I'm not thinking of.

AlignedDev
  • 8,102
  • 9
  • 56
  • 91
1

I worked out a solution for this, you simply tell the dependency injector to inject an instance of your parent router component using Parent.of(YourComponent).

import {inject, Parent} from 'aurelia-framework';
import {UsersRouter} from './router';

@inject(Parent.of(UsersRouter))
export class UserImages {
  constructor(usersRouter) {
      this.usersRouter = usersRouter;
  }

  activate() {
    this.user = this.usersRouter.user;
  }
}

You can also actually miss out the Parent.of part because the Aurelia DI system works its way up.

import {inject} from 'aurelia-framework';
import {UsersRouter} from './router';

@inject(UsersRouter)
export class UserImages {
  constructor(usersRouter) {
      this.usersRouter = usersRouter;
  }

  activate() {
    this.user = this.usersRouter.user;
  }
}
Mike
  • 7,244
  • 5
  • 21
  • 27
  • 1
    Be careful, if you navigate away from `UsersRouter` and then navigate back, you may get the old router, not the new one because `UsersRouter` may be dependency injected as a static-lifetime class which means the first one ever instantiated is the one that will be dependency injected everywhere. – Micah Zoltu May 27 '15 at 01:04
0

You can implement a generic method to pass objects:

configureRouter(config, router){
    this.router = router;
    ...

    this.router.navigateWithParams = (routeName, params) => {
        let routerParams = this.router.routes.find(x => x.name === routeName);
        routerParams.data = params;
        this.router.navigate(routeName);
    }

}

then you can use it programmatically like:

goToSomePage(){
     let obj = { someValue: "some data", anotherValue: 150.44}
     this.router.navigateWithParams("someRoute", obj );
}

finally, you can get the param on the destination page:

 activate(urlParams, routerParams)
 {
      this.paramsFromRouter = routerParams.data;
 }
Jose Luis
  • 1
  • 1
  • 1