Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 582
Nathan Chase Avatar asked Mar 13 '17 03:03

Nathan Chase


1 Answers

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>
like image 111
Matthew James Davis Avatar answered Sep 20 '22 00:09

Matthew James Davis