AngularJS-$ http.postがJSONの代わりに要求パラメーターを送信する方法はありますか?


116

jQueryのpostメソッドを介してAJAX POSTリクエストを作成している古いコードがいくつかあり、次のようになります。

$.post("/foo/bar", requestData,
    function(responseData)
    {
        //do stuff with response
    }

requestData いくつかの基本的な文字列プロパティを備えた単なるJavaScriptオブジェクトです。

Angularを使用するようにデータを移動している最中なので、この呼び出しを$ http.postに置き換えます。私は次のことを思いつきました:

$http.post("/foo/bar", requestData).success(
    function(responseData) {
        //do stuff with response
    }
});

これを行うと、サーバーから500エラー応答が返されました。Firebugを使用して、これが次のようなリクエスト本文を送信することがわかりました。

{"param1":"value1","param2":"value2","param3":"value3"}

成功したjQuery $.postは、次のように本文を送信します。

param1=value1&param2=value2&param3=value3

私がぶつかっているエンドポイントは、JSONではなく要求パラメーターを期待しています。だから、私の質問は$http.post、JSONの代わりにリクエストパラメータとしてjavascriptオブジェクトを送信するように指示する方法はありますか はい、私はオブジェクトから自分で文字列を作成できることを知っていますが、Angularがこれに対して何かを提供してくれるかどうか知りたいです。

回答:


140

構成paramsパラメーターは本文ではなくURLに文字列を追加するため、ここでは機能しないと思いますが、ここでInfeligoが提案したものに追加するのは、デフォルトの変換のグローバルオーバーライドの例です(変換する例としてjQuery paramを使用)パラメータ文字列へのデータ)。

グローバルtransformRequest関数を設定します。

var app = angular.module('myApp');

app.config(function ($httpProvider) {
    $httpProvider.defaults.transformRequest = function(data){
        if (data === undefined) {
            return data;
        }
        return $.param(data);
    }
});

このようにして、$ http.postへのすべての呼び出しは、本体をjQuery $.post呼び出しで使用される同じparam形式に自動的に変換します。

呼び出しごとに、または次のようにグローバルにContent-Typeヘッダーを設定することもできます。

$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';

呼び出しごとの非グローバルtransformRequestのサンプル:

    var transform = function(data){
        return $.param(data);
    }

    $http.post("/foo/bar", requestData, {
        headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
        transformRequest: transform
    }).success(function(responseData) {
        //do stuff with response
    });

transformRequest関数以外に何かあるのかと思っていましたが、ないようです。jQuery param関数についてお寄せいただきありがとうございます。
dnc253 2012

非グローバルper callメソッドは私にとってはうまく機能していますが、を介してグローバルにセットアップしようとすると、機能しません$httpProvider.defaults。これについての手掛かりはありますか?
Dfr

1
WRTをグローバルに構成しているのですが、私も問題を抱えています。ここに示されているスニペットを使用して実行しようとすると、エラーが発生Cannot read property "jquery" of undefined.します。これを修正するにはどうすればよいですか?PS。コールごとの変換が機能します。
kshep92 2013年

@ kshep92何が起こっているのかというと、データがないリクエストでtransformRequest関数が呼び出されているため、「データ」が定義されていません。'return $ .param(data);'の前にガードを追加しました。これを、transformRequest関数の最初の行として挿入します。 'if(data === undefined)return data;' 私が答えに加えた編集を見てください。
Jere.Jones 2013


21

Angular> = 1.4を使用している場合、カスタムまたは外部に依存しないことがわかった最もクリーンなソリューションは次のとおりです。

angular.module('yourModule')
  .config(function ($httpProvider, $httpParamSerializerJQLikeProvider){
    $httpProvider.defaults.transformRequest.unshift($httpParamSerializerJQLikeProvider.$get());
    $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
});

そして、あなたはあなたのアプリのどこでもこれを行うことができます:

$http({
  method: 'POST',
  url: '/requesturl',
  data: {
    param1: 'value1',
    param2: 'value2'
  }
});

そして、エンドポイントのPOSTリクエストで通常予想されるように、データを正しくシリアル化し、Content-Typeヘッダーでparam1=value1&param2=value2送信します。/requesturlapplication/x-www-form-urlencoded; charset=utf-8


17

AngularJSドキュメントから:

params – {Object。} – URLの後に?key1 = value1&key2 = value2に変換される文字列またはオブジェクトのマップ。値が文字列ない場合は、 JSON化されます。

したがって、パラメータとして文字列を提供します。それが必要ない場合は、変換を使用してください。もう一度、ドキュメントから:

これらの変換をローカルでオーバーライドするには、変換オブジェクトをconfigオブジェクトのtransformRequestおよび/またはtransformResponseプロパティとして指定します。デフォルトの変換をグローバルにオーバーライドするには、$ httpProviderの$ httpProvider.defaults.transformRequestおよび$ httpProvider.defaults.transformResponseプロパティをオーバーライドします。

詳細については、ドキュメントを参照してください。


私はドキュメントでparamsを見ました、そしてGloopyの言及のように、私はそれが本文ではなくURLではなく必要です。JSONの代わりにパラメーターを実行するためのオプションがあるのか​​、何か不足しているのではないかと思っていましたが、transformRequestプロパティを使用するだけでよいようです。
dnc253 2012

15

jQueryの$.param関数を使用して、requestDataのJSONデータをシリアル化します。

簡単に言うと、あなたと同じようなコードを使用する:

$http.post("/foo/bar",
$.param(requestData),
{
    headers:
    {
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
    }
}
).success(
    function(responseData) {
        //do stuff with response
    }
});

これを使用するには、AngularJSとともにページにjQueryを含める必要があります。


7

Angular 1.4以降、jQueryを使用せずにフォームデータをシリアル化できることに注意してください。

app.jsで:

module.run(function($http, $httpParamSerializerJQLike) {
  $http.defaults.transformRequest.unshift($httpParamSerializerJQLike);
});

次に、コントローラーで:

$http({
    method: 'POST',
    url: myUrl',
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    data: myData
});

この答えは素晴らしいです。AngularのPostに関する2つの主要な問題に対処します。ヘッダーは正しく設定する必要があり、jsonデータをシリアル化する必要があります。IE8サポートが必要ない場合は、1.4以降を使用してください。
mbokil 2016

私はこれを実装し、postで発生していた問題を解決しましたが、これによりパッチの動作も変更され、$ http.patch()のすべての使用が中断されたようです。
Mike Feltman 2016

5

これは少しハックかもしれませんが、問題を回避し、サーバー側でjsonをPHPのPOST配列に変換しました。

$_POST = json_decode(file_get_contents('php://input'), true);

私はこの方法を使用しましたが、嫌いです。そして、なぜこれを使わなければならないのかを理解するのに長い時間がかかりました。
meconroy

私が言ったように-それはハッキーな感じです。ほとんどのphpのように;)
TimoSolo

5

$ resourceがリクエストをキャッシュするため、カスタムhttp認証の設定にも問題があります。

これを機能させるには、次のようにして既存のヘッダーを上書きする必要があります

var transformRequest = function(data, headersGetter){
  var headers = headersGetter();
  headers['Authorization'] = 'WSSE profile="UsernameToken"';
  headers['X-WSSE'] = 'UsernameToken ' + nonce
  headers['Content-Type'] = 'application/json';
};

return $resource(
  url,
    {
    },
    {
      query: {
        method: 'POST',
        url: apiURL + '/profile',
        transformRequest: transformRequest,
        params: {userId: '@userId'}
      },
    }
);

私は誰かを助けることができたと思います。これを理解するのに3日かかりました。


たぶん、3日間の作業を節約できたと思います。ありがとう!!! すべての呼び出しにカスタムヘッダーを挿入できるように、要求の呼び出しをなんらかの方法でインターセプトできるかどうかをまだ把握しています。
marcoseu 2013

4

デフォルトのヘッダーを変更します。

$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8";

次に、JQueryの$.paramメソッドを使用します。

var payload = $.param({key: value});
$http.post(targetURL, payload);

3
   .controller('pieChartController', ['$scope', '$http', '$httpParamSerializerJQLike', function($scope, $http, $httpParamSerializerJQLike) {
        var data = {
                TimeStamp : "2016-04-25 12:50:00"
        };
        $http({
            method: 'POST',
            url: 'serverutilizationreport',
            headers: {'Content-Type': 'application/x-www-form-urlencoded'},
            data: $httpParamSerializerJQLike(data),
        }).success(function () {});
    }
  ]);

私によると、その最も簡単で最も簡単な方法...他にも多くの方法があるかもしれません
Rohit Luthra

2

クイック調整-transformRequest関数のグローバル構成で問題が発生した場合のために、Cannot read property 'jquery' of undefinedエラーを取り除くために使用しているスニペットを次に示します。

$httpProvider.defaults.transformRequest = function(data) {
        return data != undefined ? $.param(data) : null;
    }


0

私は何度もこの全体の問題のある動作を発見しました。私はそれをエクスプレス(タイピングなし)とbodyParser(dt〜body-parserタイピング付き)から使用しました。

私はファイルをアップロードするのではなく、投稿文字列で与えられたJSONを解釈するだけでした。

これrequest.bodyは単に空のjson({})でした。

多くの調査の後、ようやくこれがうまくいきました:

import { json } from 'body-parser';
...
app.use(json()); <-- should be defined before the first POST handler!

application/jsonクライアント側からのリクエスト文字列にコンテンツタイプを指定することも重要です。


typescript / node / angular環境の現在のステージで残念ながら一般的である「そして黒い雌鳥を犠牲にする」スタイルの答えを申し訳ありません。
peterh-モニカを2016年

0

AngularJS v1.4.8 +(v1.5.0)の構文

       $http.post(url, data, config)
            .then(
                    function (response) {
                        // success callback
                    },
                    function (response) {
                        // failure callback
                    }
            );

例えば:

    var url = "http://example.com";

    var data = {
        "param1": "value1",
        "param2": "value2",
        "param3": "value3"
    };

    var config = {
        headers: {
            'Content-Type': "application/json"
        }
    };

    $http.post(url, data, config)
            .then(
                    function (response) {
                        // success callback
                    },
                    function (response) {
                        // failure callback
                    }
            );
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.