Object as Query Param to Refresh Model


#1

I followed the Query Params guide (http://guides.emberjs.com/v1.11.0/routing/query-params/) and it worked great. Specifically, refreshing the model did exactly what I wanted.

I’m moving the filter to the json-api spec and filtering takes place in a filter object. So rather than:

http://localhost:3000/accounts?id=1

The server responds to:

http://localhost:3000/accounts?filter[id]=1

I tried to get the query params to work refreshing the model based on an object, but it doesn’t seem to update.

// app/controllers/accounts/index.js

import Ember from 'ember';

export default Ember.Controller.extend({
  queryParams: ['filter', 'sort'],

  filter: {},
  sort: '-id'
});


// app/routes/accounts/index.js
import Ember from 'ember';

export default Ember.Route.extend({
  queryParams: {
    filter: { refreshModel: true },
    sort: { refreshModel: true }
  },
  model: function(params) {
    return this.store.find('account', params);
  },
});

// template
<th>{{input type="text" placeholder="ID" value=filter.id}}</th>

Is it possible to have query params work with an object? And if not, is there a better way to go about supporting this without enumerating each value and then manually creating a filter param?


#2

Hey-- have you found a solution to this? I’m trying to implement pagination using the json::api spec that follows the same syntax:

?page%5Bnumber%5D=1&page%5Bsize%5D=20

JSON API Pagination


#3

Never found an answer. Ended up bailing on JSON API at the time, b/c it wasn’t baked in to Ember enough. Not sure if it’s any better now. I ended up using the RESTSerializer instead.


#4

Hi all! Hope you don’t mind me reviving such an old thread, but I’ve been working on the same issue myself, and I was able to get it working, so thought I’d share:

All you have to do is use square brackets when you define your filter:

filter: [],

If you then set the value of filter as an object, for instance:

test: {id: 1234, values:['foo', 'bar']},
actions: {
  setFilter():{
    this.set('filter', this.get('test'));
  }
}

It will serialise it in the URL by literally url encoding the object:

example.com?filter=%7B"id"%3A"1234"%2C"values"%3A%5B"foo"%2C"bar"%5D%7D

But fortunately, when you make an API call, Ember Data does the rest of the work for you, and using:

model(params){
  return this.get('store').query('account', params);
}

Will send an http request formatted like:

http://www.backend.com?filter%5Baccount%5D=1234&filter%5Bvalues%5D%5B%5D=foo&filter%5Bvalues%5D%5B%5D=bar

Which decodes into:

http://www.backend.com?filter[account]=1234&filter[values][]=foo&filter[values][]=bar

I hope this helps with future projects!


#5

Hi I am new to Ember. Rather to answer the question, I am confused why you would need queryParams in Controller since you already defined it in Route. Can someone explain what’s the difference between queryParam in Route vs Controller? Thanks


#6

Hi Jin,

Basically, the Controller and Route perform different functions in Ember. The Route determines which templates to render, which model to load, and handles redirecting to new routes based on the state of the URL. The Controller extends the model for a given route, and is a place to put additional route-based data and actions.

Query Parameters in Ember are bound to the Controller, so the Controller is where you declare query parameters and where you go to change the values of parameters. Generally speaking, all of the code related to query parameters can go in the Controller, and any time a parameter is updated, it will fire hooks in the controller it is associated with.

However, in a few situations, you may need a query parameter to be able to fire Route-based hooks instead—the most common situation for this is if you need to re-load the route’s model based on changes to a specific query parameter. When dealing with this sort of case, you need to add a declaration to the route associated with your controller that tells it to fire the extra hooks.

So basically, query parameters are defined in the Controller, but need to be referenced in the Route if there is a Route action that depends on changes to your query parameters.

There aren’t very many instances where this is necessary though, and they’re described in the Ember.js guide: https://guides.emberjs.com/release/routing/query-params/


#7

Thank you. Your answer to the post and my question is very helpful.