jQueryなしで$ httpを使用してURLエンコードされたフォームデータをPOSTするにはどうすればよいですか?


195

私はAngularJSを初めて使用するので、まず、AngularJSだけを使用して新しいアプリケーションを開発しようと思いました。

$httpAngular App を使用して、サーバー側にAJAX呼び出しを行おうとしています。

パラメータを送信するために、私は以下を試しました:

$http({
    method: "post",
    url: URL,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    data: $.param({username: $scope.userName, password: $scope.password})
}).success(function(result){
    console.log(result);
});

これは機能していますが、ではjQueryも使用してい$.paramます。jQueryへの依存を削除するために、私は試しました:

data: {username: $scope.userName, password: $scope.password}

しかし、これは失敗したようです。それから私は試しましたparams

params: {username: $scope.userName, password: $scope.password}

しかし、これも失敗したようです。それから私は試しましたJSON.stringify

data: JSON.stringify({username: $scope.userName, password: $scope.password})

私の探求に対するこれらの可能な答えを見つけましたが、失敗しました。私は何か間違ったことをしていますか?AngularJSがこの機能を提供すると確信していますが、どうやって?


私は実際の問題が何であるかはわかりませんが、これを試しましたか$http({method: 'post', url: URL, data: {username: $scope.userName, password: $scope.password}});
Mritunjay 14

1
あなたの最初の方法はうまくいくはず$scope.userNameです、定義されていますか?どうして試しなかったのdata: data
Kevin B 14

@KevinB:申し訳ありません。私は正しい編集を行いました。
Veer Shrivastav 14

@mritunjay:申し訳ありません。編集を行いました。同じことを試していました。
Veer Shrivastav 14

@Veerはうまくいきましたか、それでも問題がありますか?
V31 2014

回答:


409

データをオブジェクトからJSON文字列に変換するのではなく、URLパラメータに変換する必要があると思います。

Ben Nadelのブログから

デフォルトでは、$ httpサービスは、データをJSONとしてシリアル化し、コンテンツタイプ "application / json"で送信することにより、送信要求を変換します。値をFORMポストとしてポストする場合は、シリアル化アルゴリズムを変更し、コンテンツタイプ「application / x-www-form-urlencoded」でデータをポストする必要があります。

ここからの例。

$http({
    method: 'POST',
    url: url,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    transformRequest: function(obj) {
        var str = [];
        for(var p in obj)
        str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
        return str.join("&");
    },
    data: {username: $scope.userName, password: $scope.password}
}).then(function () {});

更新

AngularJS V1.4で追加された新しいサービスを使用するには、を参照してください


41
JQueryを使用しないでいただきありがとうございます。
OverMars 2015年

1
multipart / form-dataを送信する必要がある場合はどうなりますか?
デジェル

2
angularがjqLit​​eをangular.elementに埋め込む限り、次のことが簡単にできますreturn angular.element.param(obj);
Vicary

4
@Vicary param()はjqLit​​eに実装されていないことに注意してください-code.angularjs.org/1.3.14/docs/api/ng/function/angular.element
Alex Pavlov

1
これは行くための別の方法です var obj = {a: 1, b: 2}; Object.keys(obj).reduce(function(p, c) { return p.concat([encodeURIComponent(c) + "=" + encodeURIComponent(obj[c])]); }, []).join('&');
test30

136

AngularJSサービスのみを使用したURLエンコード変数

AngularJS 1.4以降では、2つのサービスがPOSTリクエストのデータをURLエンコードするプロセスを処理できるため、transformRequestjQueryなどの外部依存関係を使用したり、外部依存関係を使用してデータを操作する必要がなくなります。

  1. $httpParamSerializerJQLike-jQueryに触発されたシリアライザ.param()推奨

  2. $httpParamSerializer -GETリクエストのためにAngular自体が使用するシリアライザ

使用例

$http({
  url: 'some/api/endpoint',
  method: 'POST',
  data: $httpParamSerializerJQLike($scope.appForm.data), // Make sure to inject the service you choose to the controller
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded' // Note the appropriate header
  }
}).then(function(response) { /* do something here */ });

より詳細なPlunkerデモを見る


どのようにしている$httpParamSerializerJQLike$httpParamSerializer異なります

一般に、複雑なデータ構造に関しては、$httpParamSerializer「従来の」URLエンコード形式よりも使用が少ないよう$httpParamSerializerJQLikeです。

例(括弧のパーセントエンコーディングを無視):

配列のエンコード

{sites:['google', 'Facebook']} // Object with array property

sites[]=google&sites[]=facebook // Result with $httpParamSerializerJQLike

sites=google&sites=facebook // Result with $httpParamSerializer

オブジェクトのエンコード

{address: {city: 'LA', country: 'USA'}} // Object with object property

address[city]=LA&address[country]=USA // Result with $httpParamSerializerJQLike

address={"city": "LA", country: "USA"} // Result with $httpParamSerializer

ファクトリー内の$ resourceでこれをどのように使用できますか?
静物画2015年

2
$http.({...代わりにすべきである`$http.post({...
Carlos Granados

@CarlosGranadosお知らせありがとうございます。このタイプミスをこことPlunkerデモで修正しました。
Boaz 2015年

jQueryからAngularJSに移行した後、これは完全に機能しました
zero298

4
これは私が探していたAngularJS固有の答えです。ポスターがこれをベストアンサーとして選んでほしい。
Marty Chang

61

これらはすべてやりすぎ(または機能しない)のように見えます...これを実行してください:

$http.post(loginUrl, `username=${ encodeURIComponent(username) }` +
                     `&password=${ encodeURIComponent(password) }` +
                     '&grant_type=password'
).success(function (data) {

11
最後にいくつかの常識
jlewkovich '28 / 07/28

これは間違ったcontent-typeヘッダーでリクエストを送信しませんか?
Phil

それは私にとってはうまくいきました...ヘッダーが何かはわかりませんが、リクエストはうまくいき、認証に成功しました。テストして、私たちに知らせてみませんか。
Serj Sagan

5
@Philはサーバーに依存する可能性があると思いますが、設定の引数として{headers:{'Content-Type': 'application / x-www-form-urlencoded'}}を追加するか、またはuse moicesの回答のような$ http(config)コンストラクターが示しています。いずれにしても、これは受け入れられた回答よりも優れています。魔法の変換を導入せず、補助サービスのユーザーを必要としないためです。ありがとう!
Bungle氏、2016年

23

問題はJSON文字列形式です。データで単純なURL文字列を使用できます。

$http({
    method: 'POST',
    url: url,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    data: 'username='+$scope.userName+'&password='+$scope.password
}).success(function () {});

7
encodeURIComponent($scope.userName)データをURLエンコードするために使用する必要があります。そうでない場合、ユーザーが次のような値を入力すると、パラメーターが破損します"&myCustomParam=1"
IvanHušnjakSep

2
これが私にとってうまくいった唯一の答えです!私は成功をスキップしましたが、$ http形式は適切です
xenteros

4

ここにそれがあるべき姿です(そしてバックエンドの変更をしないでください...確かに...フロントスタックがサポートしていないapplication/x-www-form-urlencoded場合は捨ててください...うまくいけばAngularJSがサポートします!

$http({
     method: 'POST',
     url: 'api_endpoint',
     headers: {'Content-Type': 'application/x-www-form-urlencoded'},
     data: 'username='+$scope.username+'&password='+$scope.password
 }).then(function(response) {
    // on success
 }, function(response) {
    // on error
 });

AngularJS 1.5の魅力のように動作します

人々は、あなたにいくつかのアドバイスを与えましょう:

  • 、forget about 、callback .then(success, error)を処理するときにpromiseを使用します(廃止予定のため)$http.sucess.error

  • angularjsサイトのここからJSON_CALLBACK文字列を、コールバックパラメータ値の移動先を指定するためのプレースホルダとして使用することはできなくなりました。

データモデルがユーザー名とパスワードだけのより複雑な場合でも、それを行うことができます(上記で提案)。

$http({
     method: 'POST',
     url: 'api_endpoint',
     headers: {'Content-Type': 'application/x-www-form-urlencoded'},
     data: json_formatted_data,
     transformRequest: function(data, headers) {
          return transform_json_to_urlcoded(data); // iterate over fields and chain key=value separated with &, using encodeURIComponent javascript function
     }
}).then(function(response) {
  // on succes
}, function(response) {
  // on error
});

以下のためのドキュメントencodeURIComponent見つけることができるここに


3

フォームの場合は、ヘッダーを次のように変更してみてください。

headers[ "Content-type" ] = "application/x-www-form-urlencoded; charset=utf-8";

そして、それがフォームでも単純なjsonでもない場合は、次のヘッダーを試してください。

headers[ "Content-type" ] = "application/json";

何も受け取りません。まだ空の$_POST配列が届きま​​した。
Veer Shrivastav

これはあなたのコントローラーの$ http呼び出しですか?
V31、2014

もう1つは、サーバーエンドphpですか。
V31、2014

私は同じための解決策を見つけましたあなたはまだ@Veerの問題を抱えていますか?
V31、2014

2
$http({

    method: "POST",
    url: "/server.php",
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    data: "name='Олег'&age='28'",


}).success(function(data, status) {
    console.log(data);
    console.log(status);
});

4
コードのみの回答はコミュニティにとって有用ではありません。回答方法を
abpatil 2017

1

$ HTTPドキュメントこれは動作するはずです。..

  $http.post(url, data,{headers: {'Content-Type': 'application/x-www-form-urlencoded'}})
    .success(function(response) {
         // your code...
     });

@Kevinこれについてはよくわかりませんが、文字列を送信しようとしたときにエラーが表示されました
Srinath

@KevinB Fine..I got it..i文字列の送信中にヘッダーを変更する必要があると思います... stackoverflow.com/a/20276775/2466168
Srinath

1
正しいものを送信しても、何らかの方法でurlencodeする必要があるにはheaders影響しないことに注意してくださいdata
Boaz

データは引き続きjsonで送信されます。データをx-www-form-urlencodedにエンコードする必要があります。ヘッダーを追加するだけでは不十分です
wendellmva

1

プレーンなJavaScriptオブジェクトを投稿する必要があります。

           var request = $http({
                method: "post",
                url: "process.cfm",
                transformRequest: transformRequestAsFormPost,
                data: { id: 4, name: "Kim" }
            });

            request.success(
                function( data ) {
                    $scope.localData = data;
                }
            );

PHPをバックエンドとして使用している場合は、さらに変更を加える必要があります。PHPサーバー側を修正するには、このリンクをチェックアウトしてください


それはまさに彼が求めたものではありません、彼は投稿されたjsonのもので問題に遭遇しているので、x-www-form-urlencodedとしてそれらをどのように得ることができるかを具体的に尋ねました。
ppetermann、2015年

@ppetermannは、投票する前に質問の編集履歴を確認しましたか?
harishr '20

1

遅い回答ですが、角度のあるUrlSearchParamsが非常にうまく機能していることがわかりました。これは、パラメーターのエンコードも処理します。

let params = new URLSearchParams();
params.set("abc", "def");

let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded'});
let options = new RequestOptions({ headers: headers, withCredentials: true });
this.http
.post(UrlUtil.getOptionSubmitUrl(parentSubcatId), params, options)
.catch();

0

これでうまくいきました。フロントエンドにはangular、バックエンドにはlaravel phpを使用しています。私のプロジェクトでは、angular webがjsonデータをlaravelバックエンドに送信します。

これは私の角度コントローラです。

var angularJsApp= angular.module('angularJsApp',[]);
angularJsApp.controller('MainCtrl', function ($scope ,$http) {

    $scope.userName ="Victoria";
    $scope.password ="password"


       $http({
            method :'POST',
            url:'http://api.mywebsite.com.localhost/httpTest?callback=JSON_CALLBACK',
            data: { username :  $scope.userName , password: $scope.password},
            headers: {'Content-Type': 'application/json'}
        }).success(function (data, status, headers, config) {
            console.log('status',status);
            console.log('data',status);
            console.log('headers',status);
        });

});

これは私のphpバックエンドのlaravelコントローラーです。

public function httpTest(){
        if (Input::has('username')) {
            $user =Input::all();
            return  Response::json($user)->setCallback(Input::get('callback'));
        }
    }

これは私のララベルのルーティングです

Route::post('httpTest','HttpTestController@httpTest');

ブラウザでの結果は

ステータス200
データJSON_CALLBACK({"ユーザー名": "ビクトリア"、 "パスワード": "パスワード"、 "コールバック": "JSON_CALLBACK"}); httpTesting.js:18ヘッダー関数(c){a ||(a = sc(b)); return c?a [K(c)] || null:a}

postmanと呼ばれるクロム拡張があります。を使用して、機能しているかどうかにかかわらず、バックエンドURLをテストできます。 https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en

うまくいけば、私の答えがあなたを助けるでしょう。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.