Ember.js: Query params with values null or undefined get serialized into strings

Created on 20 Mar 2014  ·  21Comments  ·  Source: emberjs/ember.js

Most helpful comment

_In case anyone find this via Google._

The issue is basically solved, but an edge case remain where if the query param isn't set on the controller it will serialize null into 'null'.

var AnimalsController = Ember.Controller.extend({

  queryParams: ['myCat']
  // myCat: null // deliberately not set, to illustrate the issue

});

export default AnimalsController;

All 21 comments

thanks @denisnazarov for tracking this one down.

ping señor @machty

@machty we could use your help on this

So after struggling with this last night I'm not sure that this is totally undesirable. Say you have the following controller.

App.MyController = Ember.Controller.extend({
  queryParams: ['filters'],
  filters: ['starred']
});

If you set filters to null and refresh the page what is the expected behavior? If you don't seralize null into the url the controller property will be set to its default value.

This is similar to the problem in the previous implementation that it was ambiguous between falsy values and the actual value of false. Now it seems its ambiguous between a defaultValue and null or undefined.

Here's another example using boolean query params: http://emberjs.jsbin.com/hamev/2/edit

If the default value is set to null, setting it to true or false actually sets it to the string version, 'true' or 'false'.

@HeroicEric so what's the compelling reason for setting it to null if in it's life time it's going to be the boolean true / false ?

That might have come out wrong; I'm just curious what the use cases are for all these serialization corner cases.

@machty I tried to show an example use case in the jsbin.

For example, I'm displaying a list of users and I want to be able to filter them so that the list contains either All Users, Admin Users, or Non-Admin Users. When I want to see All Users I would basically just be removing the filter.

Are situations like this not what query params are meant for?

Ideally the URLs would be something like this:

/users shows all the users
/users?admin=true shows all the admins
/users?admin=false shows all the users that are not admins

@HeroicEric @machty I think the idea was that if the defaultValue on the controller wasn't defined (null or undefined) that it would default to using strings. This would explain why true and false end up as their string versions since the serialization defaults to strings.

I think if you want a property to be set to null then we need to get the type from somewhere else. @machty would this be a good reason for the ability of adding the type to the queryParams configuration on the route?

If we had this then you could set the type as 'boolean' and set the default to null.

I have this JSBin example, and I wonder if what I'm seeing is related to this issue:

http://jsbin.com/dipajezi/1/edit

Basically, I have this foo query parameter with a null default value, and the first time my model hook gets called when the application starts, the value of the parameter is null. When the parameter value is null, I do not want to use this parameter to query the server, because it means "no value".

Query: ?page=1

When I click on the NextPage button, I transition again but this time I change the page query parameter. This time the foo query parameter has a string value of "null", which is kind of weird. In this case I would still want to have a value of null, so that I can easily verifiy that the parameter does not have a value.

Query: ?page=1 and not ?page=1&foo=null

Finally, when I click on the ChangeFoo button, I transition again, this time setting the value of the foo query parameter to whatever value. Now that the value is not null, I can use this value to construct my query string.

Query ?page=1&foo=3

@raytiley Just wrote a note on https://github.com/raytiley/ember.js/commit/26a3f8569edb58f8644ce4f9cec7000276c327a6#diff-0631ecfe6138cf2c2eb2d94369c3e846R1640.

If I set a qp to null explicitly, then it is cast to a string in the model hook. This doesn't seem right, since null should represent "no value", and if an individual does want the null string, then they can create it based on the value null.

Otherwise if you want to pass QPs that have values only, you have to do params.myQP && params.myQp !== "null"..

I think this is out of date but will reopen if someone can demonstrate the issue in a JSBin that uses the following ember.js: http://s3.amazonaws.com/machty/to_s3_uploads/ember-9fbe6c2a-c124-5c2e-0414-f5ed36c2a1a2.js

_In case anyone find this via Google._

The issue is basically solved, but an edge case remain where if the query param isn't set on the controller it will serialize null into 'null'.

var AnimalsController = Ember.Controller.extend({

  queryParams: ['myCat']
  // myCat: null // deliberately not set, to illustrate the issue

});

export default AnimalsController;

Regarding @HeroicEric's use case, the controller won't know how to intelligently serialize based on what the value will be in its lifetime. This seems to be working in the most recent version (2.6):

export default Ember.Controller.extend({
  queryParams: [{ 
     redevelopment: { 
         type: 'boolean' 
     } 
  }],
  redevelopment: null
});

Working ember twiddle: https://ember-twiddle.com/3afa1091106a91ce2c1734ae2998bc3f?openFiles=controllers.application.js%2C&route=%2F%3Fredevelopment%3Dtrue

Since when do QPs allow setting the type? Or are you just proposing a new API?

It seems to be undocumented. Looking here, it seems it can be overridden.

Oh, that's nice!

Thanks, @allthesignals, it's so helpful for your solution.

How about this solution?

{ key: undefined } to ? _(not included)_
{ key: null } to ?key
{ key: '' } to ?key=
{ key: 'null' } to ?key=null

Good list!

I'd vote for this:
{ key: undefined } to [nothing] _(not included)_
{ key: null } to [nothing] _(not included)_
{ key: '' } to ?key
{ key: 'null' } to ?key=null

and possibly also:

{ key: false } to [nothing] _(not included)_
{ key: true } to ?key

Was this page helpful?
0 / 5 - 0 ratings