Passing dynamic query-params as an object in link-to helper


#1

Hello, I have a requirement as to pass query-params dynamically.

I have demostrated my idea here

model: [ 
      {
      "routeName":"laptop",
      "param": {"color":"blue"}
      },
      {
      "routeName":"mobile",
      "param": {"size":"5.5"}
      },
      {
      "routeName":"notebook",
      "param": {"display":"HD"}
      }
    ];


{{#each model as |obj|}}

     {{#if (equal obj.routeName 'laptop')}}

          {{#link-to obj.routeName (query-params color=obj.param.color)}}
                {{obj.routeName}}
          {{/link-to}}

     {{/if}}

     {{#if (equal obj.routeName 'mobile')}}

           {{#link-to obj.routeName (query-params size=obj.param.size)}}
                {{obj.routeName}}
           {{/link-to}}

     {{/if}}

     {{#if (equal obj.routeName 'notebook')}}
           {{#link-to obj.routeName (query-params display=obj.param.display)}}
                {{obj.routeName}}
           {{/link-to}}
     {{/if}}

  {{/each}}

Since, {{link-to}} doesn’t support dynamic querying I had to include checks for passing query-param.

If {{link-to supports dynamic passing of query-params like below

    {{#each model as |obj|}}

        {{#link-to obj.routeName (query-params obj.param) }}
              {{obj.routeName}}
       {{/link-to}}

    {{/each}}

The code would be more pretty without any if checks !


#2

+1 I aggree! Would be extremely helpful to be able to pass a { param: value } dictionary to query-params.


#3

I know this is super old, but I just ran into this exact issue, and I found a way to make it work. Note that I don’t think this is actually documented anywhere… I had to look at the source code to link-to to figure this out.

What you do is create a params array that you pass into link-to via the “params” attribute (eg. {{#link-to params=params}}). Each element of the array is a route segment (eg. [ 'cars', 'models', 'years' ]), and the last element can optionally be a special query param object of the format:

{
  isQueryParams: true,
  values: {
    key1: value1,
    key2: value2
  }
}

So in your case, I would set up a Computed property that contains all the params for each object in your model, as such:

processed: Ember.computed('model', function() {
  let data = this.get('model').map((obj) => {
    let params = [ myObject.routeName ];
    let queryParams = { isQueryParams: true, values: {} };
    if (obj.routeName === 'laptop') {
      queryParams.values.color = obj.param.color;
    }
    if (obj.routeName === 'mobile') {
      queryParams.values.size = obj.param.size;
    }
    if (obj.routeName === 'notebook') {
      queryParams.values.display = obj.param.display;
    }
    params.push(queryParams);
    return {
      routeName: obj.routeName,
      params: params
    };
  });
  return data;
}

And then in your template, it’d look something like:

{{#each processed as |data|}}
  {{#link-to params=data.params}}
    data.routeName
  {{/link-to}}
{{/each}}

Again, I don’t think using the params attribute of link-to or creating a query-params object as part of the params object is documented anywhere, so I don’t know how much of a hack this is.


#4

@accelerate you saved my life, at least for this evening!

In my project there’s a very specific feature that require this functionality and I can’t see any other way to implement it apart from dynamic query params.


#5

I made an ember-helper that generates it for you. Gist here: https://gist.github.com/lcpriest/db74e742c632372479bee8a65af85825

import Ember from 'ember';

export function dynamicParams([routeName, params]/*, hash*/) {
  return [
    routeName,
    {
      isQueryParams: true,
      values: params
    }
  ];
}

export default Ember.Helper.helper(dynamicParams);

Usage:

{{link-to 'test-link' params=(dynamic-params routeName dynamicQueryParameters)}}