Search code examples
ember.jsquery-stringember-query-params

How to efficiently store records as Ember query parameters


Background: The user can filter a list based on tags, every tag is an Ember Data model. The selected filtering tags should be stored in the URL via query parameters. I also want to display the selected tags in the interface.

What's the best way to go about this?

I'm pretty sure I only want to store the IDs, but if I do this I have to maintain a separate variable / computed property where I store the actual record of the ID which comes from the query parameters. This kind of duplication seems wrong to me.

Apart from this issue I don't know if I should use an array query parameter or build an comma separated string of the IDs. If I do the former I end up with ugly URLs like ?tags=%5B"3"%5D. But doing the later means doing even more work.

So what's your approach to this kind of problem? I hope I'm missing something obvious that doesn't have so many downsides :)


Solution

  • Easy!

    1. Find out which non-alphanumeric characters are not getting encoded in URLs. Using this tool, I found these characters: ~!*()_-.
    2. Pick one character that is not used in your tag names. Let's say it's *. Use it as a delimiter.
    3. Use tag names for tag ids. Or at least enforce unique tag names.

    Then you've got a nice readable query:

    ?tags=foo*bar*baz&search=quux
    

    To implement custom query param serialization/deserialization, do this:

    Ember.Route.reopen({
      serializeQueryParam: function(value, urlKey, defaultValueType) {
        if (defaultValueType === 'array') {
          return `${value.join('*')}`;
        }
        return this._super(...arguments);
      },
    
      deserializeQueryParam: function(value, urlKey, defaultValueType) {
        if (defaultValueType === 'array') {
          return value.split('*');
        }
        return this._super(...arguments);
      }
    });
    

    Demo: app, code.

    If you must use numeric tag ids in query params (for example, your tag names aren't unique), then you need some more customization: app, code.