Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query params with values null or undefined get serialized into strings #4570

Closed
denisnazarov opened this issue Mar 20, 2014 · 21 comments
Closed
Labels

Comments

@denisnazarov
Copy link
Contributor

serializeQueryParam: function(value, urlKey, defaultValueType) {
// urlKey isn't used here, but anyone overriding
// can use it to provide serialization specific
// to a certain query param.
if (defaultValueType === 'array') {
return JSON.stringify(value);
}
return '' + value;
},

@denisnazarov denisnazarov changed the title Query params with values null or undefined get serialized into "null" and "undefined" Query params with values null or undefined get serialized into strings Mar 20, 2014
@stefanpenner
Copy link
Member

thanks @denisnazarov for tracking this one down.

ping señor @machty

@machty
Copy link
Contributor

machty commented Mar 20, 2014

@machty we could use your help on this

@raytiley
Copy link
Contributor

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.

@HeroicEric
Copy link
Sponsor Member

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'.

@machty
Copy link
Contributor

machty commented Mar 21, 2014

@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 ?

@machty
Copy link
Contributor

machty commented Mar 21, 2014

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

@HeroicEric
Copy link
Sponsor Member

@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?

@HeroicEric
Copy link
Sponsor Member

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

@raytiley
Copy link
Contributor

@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.

raytiley added a commit to raytiley/ember.js that referenced this issue Mar 24, 2014
@wagenet wagenet added the bug label Apr 2, 2014
@ggohierroy
Copy link

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

@heyjinkim
Copy link
Contributor

@knownasilya
Copy link
Contributor

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"..

@machty
Copy link
Contributor

machty commented Jun 2, 2014

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

@machty machty closed this as completed Jun 2, 2014
@sandstrom
Copy link
Contributor

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;

@allthesignals
Copy link
Contributor

allthesignals commented Jun 17, 2016

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

@knownasilya
Copy link
Contributor

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

@allthesignals
Copy link
Contributor

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

@knownasilya
Copy link
Contributor

Oh, that's nice!

@JsFront66666
Copy link

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

CvX pushed a commit to CvX/ember.js that referenced this issue Aug 30, 2017
…ined into url

# Conflicts:
#	packages/ember/tests/routing/query_params_test.js
#	packages_es6/ember-routing/lib/system/route.js
CvX pushed a commit to CvX/ember.js that referenced this issue Oct 10, 2017
…ined into url

# Conflicts:
#	packages/ember/tests/routing/query_params_test.js
#	packages_es6/ember-routing/lib/system/route.js
kategengler pushed a commit that referenced this issue Oct 17, 2017
…to url

# Conflicts:
#	packages/ember/tests/routing/query_params_test.js
#	packages_es6/ember-routing/lib/system/route.js

(cherry picked from commit c157b99)
rwjblue pushed a commit that referenced this issue Oct 29, 2017
…to url

# Conflicts:
#	packages/ember/tests/routing/query_params_test.js
#	packages_es6/ember-routing/lib/system/route.js

(cherry picked from commit c157b99)
@KES777
Copy link

KES777 commented May 31, 2019

How about this solution?

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

@sandstrom
Copy link
Contributor

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests