amiel / ember-data-url-templates

an ember-addon to allow building urls with url templates instead of defining buildURL
https://github.com/amiel/ember-data-url-templates/wiki
MIT License
129 stars 22 forks source link

Nested query objects not working #17

Closed mattbearman closed 6 years ago

mattbearman commented 8 years ago

Not sure if I'm doing something wrong, but I've checked the docs and played around a lot, and I can't seem to get a query with nested params working.

Eg: with the following query object:

{ filter: { offset: 0 }}

I'd expect the {?query*} part of the template to render as ?filter[offset]=0, but instead I get ?filter=%5Bobject%20Object%5D

amiel commented 8 years ago

@mattbearman I don't think that RFC6570 includes support for nested params like this.

For now it should work if you convert your query object to something like:

{ "filter[offset]": 0 }
aaronfischer commented 7 years ago

@amiel Is there a hook somewhere we can tie into to convert these nested objects into the flat structure you noted above?

(seeing this problem upgrading from 0.1.X to 0.2.X)

amiel commented 7 years ago

@Aaronfischer Yes, you can define any urlSegment to use the query. Something like this:

urlSegments: {
  query(type, id, snapshot, query) {
    // this is your hook
  },
}

Alternatively, you could revert the change in 0.2.x that prevents Ember from appending params to the url. To do this, overwrite sortQueryParams. The simplest thing would be to return params:

sortQueryParams(params) {
  return params;
}

However, if you need query params sorted, you can copy over the official implementation.

amiel commented 7 years ago

FYI: I've got a little more time to work on ember-data-url-templates now and I'm planning to at least try out a feature that supports these nested structures.

basz commented 6 years ago

@amiel would you happen to have an implementation that you're willing to share to convert a nested object into a flat structure as mentioned?

basz commented 6 years ago

I think I found something:

const flatten = function(arr) {
  let newObj = {};
  dive('', arr, newObj);
  return newObj;
};

const dive = function(currentKey, into, target) {
  for (let i in into) {
    if (into.hasOwnProperty(i)) {
      let newKey = i;
      let newVal = into[i];

      if (currentKey.length > 0) {
        newKey = `${currentKey}[${i}]`;
      }

      if (typeof newVal === 'object') {
        dive(newKey, newVal, target);
      } else {
        target[newKey] = newVal;
      }
    }
  }
};

plus

urlSegments: {
    query(type, id, snapshot, query) {
      if (this.get('queryUrlTemplate')) {
        return flatten(query);
      }

      return query;
    }
  }
amiel commented 6 years ago

@basz Wow! flatten/dive look great! Would you be interested in making a PR with these? or can I use this code and attribute it to you?

basz commented 6 years ago

I would if I had some time, but unfortunately I don't. But go ahead and use it. I found it here, so attribution should go to Marie I suppose.

https://stackoverflow.com/questions/34513964/how-to-convert-this-nested-object-into-a-flat-object

amiel commented 6 years ago

@mattbearman @basz @Aaronfischer If you have a chance, would you try out #43 and see if that works for you?

basz commented 6 years ago

Just tested, I find no issues. So... thank you

amiel commented 6 years ago

Alright! Thanks for testing. Apparently I need to fix some issues with CI, but once that's figured out I'll try to make a release.