How do you dynamically bind route-href parameters in Aurelia?
Asked Answered
T

2

7

I'm using pushState, and not using hashes for the URL structure.

I have a route, and it has a few parameter bindings - some optional:

route: [                        
     'chart/:chartType/:id',
     'chart/:chartType/:id/:view?',
     'chart/:chartType/:id/page/:page?',
     'chart/:chartType/:id/:view?/page/:page?'
], 

and then I've got my route-href, and I have the necessary bindings on there:

route-href="route.bind: chart; params.bind: { id: chartId, chartType: type, view: viewType, page: pageNum }"

...but what if I don't ALWAYS want all route parameters for a route-href? As in, I'd like to be able to link to just a route that uses chartType and id without having to create separate routes for every single parameter combination I have on this route.

I know I can use "?" in the router config to designate a route optional, but how do I make the parameters optional in my route-href links?

Doing something like this throws an error:

route-href="route.bind: chart; params.bind: { id: chartId, chartType: type, view?: viewType, page?: pageNum }"

and I can't seem to use .bind syntax, like this (which also errors):

route-href="route.bind: chart; params.bind: { id: chartId, chartType: type, view.bind: hasViewParam, page.bind: hasPageParam }"

What's the magic syntax trick here?

Tummy answered 13/3, 2017 at 3:13 Comment(0)
H
4

Try creating a chartParams property. Update this property whenever you change chart. Then, you can do this route-href="route.bind: chart; params.bind: chartParams. (I haven't tested this approach but I think it's gonna work)

Another option is generating the route manually. For example:

this.myRoute = this.router.generate(routeName, params);

Then, you can bind it to the link tag:

<a href.bind="myRoute">My Route</a>
Hippogriff answered 13/3, 2017 at 12:29 Comment(1)
Which answer doesn't work? The first or the second? There are 2 separated answersHippogriff
D
6

The problem is that while Aurelia can observe primitives, objects and arrays, it can't observe properties of objects or elements of arrays.

<a route-href="route.bind: chart; params.bind: { id: chartId, chartType: type, view: viewType, page: pageNum }">link</a>

This will work but will not update when chartId, type, viewType, and pageNum are updated. The value passed to the binding was the { id, chartType view, page } object, and Aurelia can't observe the properties of this object. Therefore, the best thing to do is to generate an object.

Perhaps in your view model you have:

export class ViewModel {
  chartId;
  type;
  viewType;
  pageNum;
}

Enhance it to this:

import { observable } from 'aurelia-framework';

export class ViewModel {

  @observable({ changeHandler: 'generateLinkParams'}) chartId;
  @observable({ changeHandler: 'generateLinkParams'}) type;
  @observable({ changeHandler: 'generateLinkParams'}) viewType;
  @observable({ changeHandler: 'generateLinkParams'}) pageNum;
  linkParams;

  generateLinkParams() {
    const { chartId, type, viewType, pageNum } = this;
    this.linkParams = { chartId, type, viewType, pageNum };
  }
}

Now, since the value of the linkParams object is being updated, and not just its properties, Aurelia will observe it. This results in the solution Fabio gave:

<a route-href="route.bind: chart; params.bind: linkParams">link</a>
Duration answered 10/12, 2017 at 10:50 Comment(0)
H
4

Try creating a chartParams property. Update this property whenever you change chart. Then, you can do this route-href="route.bind: chart; params.bind: chartParams. (I haven't tested this approach but I think it's gonna work)

Another option is generating the route manually. For example:

this.myRoute = this.router.generate(routeName, params);

Then, you can bind it to the link tag:

<a href.bind="myRoute">My Route</a>
Hippogriff answered 13/3, 2017 at 12:29 Comment(1)
Which answer doesn't work? The first or the second? There are 2 separated answersHippogriff

© 2022 - 2024 — McMap. All rights reserved.