简体   繁体   中英

Angular $http attach data as object

I'm trying to get list of tracks from soundcloud API with angularjs.
The parameters i'm trying to send are:
1) client_id (string)
2) duration (object with two properties).

Here's the code:

    var CLIENT_ID = 'a81f01ef5d0036415431e8be76c8db0e';
    var TRACKS_URL = 'https://api.soundcloud.com/tracks.json';

    var app = angular.module('soundcloud', []);

    app.controller('tracksController', function ($scope, $http) {

        $http({
            url: 'https://api.soundcloud.com/tracks.json',
            method: 'GET',
            data: {
                client_id: CLIENT_ID,
                duration: { // in milliseconds
                    from: 300000,
                    to: 400000
                }
            }
        })
            .success(function (data) {
                $scope.trackList = data;
            })
            .error(function () { alert('error'); });
    });

These parameters aren't recognized at all when I check the request in the broweser's debugger.

I tried to use 'params' instead of 'data', but this way it turns the 'duration' object to json --> then I get status 500 in response.
When I only send the client_id in params, it works fine because there's no object, only string.

jQuery's ajax method works fine: https://jsfiddle.net/oacwz1up/3/

What should I do ? How can I send the parameters normally ?
Help please! Thanks!

This happens because Angular serializes the request parameters differently than JQuery.

Angular 1.4 will address this problem introducing a paramSerializer property on the $http config object (and on $httpProvider.defaults ). This can be used for arbitrarily serializing the requests parameters (for all or a particular request).

Note, that the feature is available only since v1.4.0-rc.0 .


Besides the default serializer (which converts objects to JSON strings), there is an additional built-in serializer that emulates JQuery's param() : $httpParamSerializerJQLike .

You can use it like this:

$http.get(<API_URL>, {
  params: {...},
  paramSerializer: '$httpParamSerializerJQLike'
});

See, also, this short demo .


If you are using an older version of Angular, you could do one of the following:

  1. Construct the whole URL (including the query string) yourself (possibly using an $http request interceptor to automatically apply this to all requests).

  2. Keep the params in a flat format that will result in Angular's serializing them as expected:

     var REQ_PARAMS = { client_id: 'a81f01ef5d0036415431e8be76c8db0e', 'duration[from]': 200000, 'duration[to]': 205000 }; 

If you look at $http documentation , on request it applies a default transformation which is $http.defaults.transformRequest and as described will do the following (as you saw) :

If the data property of the request configuration object contains an object, serialize it into JSON format.

What you need to do is override this function by specifying your own transformRequest object.

function appendTransform(defaults, transform) {

  // We can't guarantee that the default transformation is an array
  defaults = angular.isArray(defaults) ? defaults : [defaults];

  // Append the new transformation to the defaults
  return defaults.concat(transform);
}

  $http({
      url: '...',
      method: 'GET',
      transformResponse: appendTransform($http.defaults.transformResponse, function(value) {
        return doTransform(value);
      })
  });

You need to find a way to get the same syntax as jQuery provide which is :

https://api.soundcloud.com/tracks.json?client_id=a81f01ef5d0036415431e8be76c8db0e&duration[from]=200000&duration[to]=205000

Use a condition is is an object and generate manually your String. Should not be difficult.

that's a strange API - I don't know why they don't do something like "duration_from" rather than requiring duration[from] - as suggested you could certainly transform the request, but if this is just a one off you could also try simply hard-coding it using url escaped values for [ and ] :

 var dataToSend = {
     client_id: 'a81f01ef5d0036415431e8be76c8db0e',
     'duration%5Bfrom%5D': 200000,
     'duration%5Bto%5D': 205000
 }; 
$http.get('http://api.soundcloud.com/tracks.json', {params:dataToSend});

The params property is way to transform query in restful way. Just transform data in dataToSend object, and it will work.

This is a URL that should be created:

https://api.soundcloud.com/tracks.json?client_id=a81f01ef5d0036415431e8be76c8db0e&duration%5Bfrom%5D=200000&duration%5Bto%5D=205000

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM