Bagaimana cara POST data formulir urlencoded dengan $ http tanpa jQuery?

195

Saya baru mengenal AngularJS, dan untuk awalnya, saya berpikir untuk mengembangkan aplikasi baru hanya menggunakan AngularJS.

Saya mencoba membuat panggilan AJAX ke sisi server, menggunakan $httpdari Aplikasi Angular saya.

Untuk mengirim parameter, saya mencoba yang berikut:

$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);
});

Ini berfungsi, tetapi menggunakan jQuery juga di $.param. Untuk menghapus ketergantungan pada jQuery, saya mencoba:

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

tetapi ini tampaknya gagal. Kemudian saya mencoba params:

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

tetapi ini juga tampaknya gagal. Kemudian saya mencoba JSON.stringify:

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

Saya menemukan jawaban yang mungkin untuk pencarian saya, tetapi tidak berhasil. Apakah saya melakukan sesuatu yang salah? Saya yakin, AngularJS akan menyediakan fungsionalitas ini, tetapi bagaimana caranya?

Veer Shrivastav
sumber
Saya tidak tahu apa masalah sebenarnya tetapi apakah Anda mencoba ini$http({method: 'post', url: URL, data: {username: $scope.userName, password: $scope.password}});
Mritunjay
1
Metode pertama Anda harus bekerja, $scope.userNamedidefinisikan? kenapa kamu tidak mencoba data: data?
Kevin B
@KevinB: maaf .. Saya telah melakukan edit yang benar.
Veer Shrivastav
@ munjunjay: maaf .. saya telah melakukan edit .. Saya mencoba yang sama.
Veer Shrivastav
@ Vik apakah itu berhasil atau Anda masih memiliki masalah?
V31

Jawaban:

409

Saya pikir yang perlu Anda lakukan adalah mengubah data Anda dari objek bukan ke string JSON, tetapi ke url params.

Dari blog Ben Nadel .

Secara default, layanan $ http akan mengubah permintaan keluar dengan membuat serial data sebagai JSON dan kemudian mempostingnya dengan tipe konten, "application / json". Ketika kita ingin memposting nilai sebagai posting FORMULIR, kita perlu mengubah algoritma serialisasi dan memposting data dengan tipe konten, "application / x-www-form-urlencoded".

Contoh dari sini .

$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 () {});

MEMPERBARUI

Untuk menggunakan layanan baru yang ditambahkan dengan AngularJS V1.4, lihat

allenhwkim
sumber
41
Terima kasih karena tidak menggunakan JQuery!
OverMars
1
bagaimana jika saya perlu mengirimkan data multi-formulir / formulir?
Dejell
2
Selama angular menyematkan jqLite di bawah angular.element, Anda cukupreturn angular.element.param(obj);
Vicary
4
@Vicary Perlu diingat bahwa param () tidak diimplementasikan di jqLite - code.angularjs.org/1.3.14/docs/api/ng/function/angular.element
Alex Pavlov
1
ini adalah cara lain untuk pergi var obj = {a: 1, b: 2}; Object.keys(obj).reduce(function(p, c) { return p.concat([encodeURIComponent(c) + "=" + encodeURIComponent(obj[c])]); }, []).join('&');
test30
136

Variabel penyandian URL hanya menggunakan layanan AngularJS

Dengan AngularJS 1.4 dan yang lebih baru, dua layanan dapat menangani proses penyandian url data untuk permintaan POST, menghilangkan kebutuhan untuk memanipulasi data dengan transformRequestatau menggunakan dependensi eksternal seperti jQuery:

  1. $httpParamSerializerJQLike- serializer yang terinspirasi oleh jQuery's .param()( disarankan )

  2. $httpParamSerializer - serializer yang digunakan oleh Angular sendiri untuk permintaan GET

Contoh penggunaan

$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 */ });

Lihat demo Plunker yang lebih bertele-tele


Bagaimana $httpParamSerializerJQLikedan $httpParamSerializerberbeda

Secara umum, tampaknya $httpParamSerializermenggunakan format penyandian url yang lebih "tradisional" daripada $httpParamSerializerJQLikeketika datang ke struktur data yang kompleks.

Misalnya (mengabaikan persen penyandian kurung):

Pengkodean array

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

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

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

Pengkodean objek

{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
Boas
sumber
Bagaimana kita bisa menggunakan ini pada $ resource di dalam pabrik?
stilllife
2
Harus $http.({...bukannya `$http.post({...
Carlos Granados
@CarlosGranados Terima kasih telah memperhatikan. Mengoreksi kesalahan ketik ini di sini dan di demo Plunker.
Boaz
Ini bekerja dengan sempurna setelah bermigrasi dari jQuery ke AngularJS
zero298
4
Ini adalah jawaban spesifik AngularJS yang saya cari. Saya berharap poster akan memilih ini sebagai jawaban terbaik.
Marty Chang
61

Semua ini kelihatannya berlebihan (atau tidak berfungsi) ... lakukan saja ini:

$http.post(loginUrl, `username=${ encodeURIComponent(username) }` +
                     `&password=${ encodeURIComponent(password) }` +
                     '&grant_type=password'
).success(function (data) {
Serj Sagan
sumber
11
Akhirnya beberapa akal sehat
jlewkovich
Bukankah ini akan mengirim permintaan dengan header tipe konten yang salah?
Phil
Itu berfungsi untuk saya ... tidak yakin apa headernya, tetapi permintaan itu berhasil dan diizinkan untuk mengotentikasi dengan sukses. Mengapa Anda tidak mengujinya dan beri tahu kami.
Serj Sagan
5
@Phil Saya kira itu mungkin tergantung pada server, saya mendapat permintaan yang buruk, sampai saya menambahkan {header: {'Tipe-Konten': 'application / x-www-form-urlencoded'}} sebagai config arg, atau penggunaan pasokan konstruktor $ http (config) seperti yang ditunjukkan oleh jawaban moices. Either way ini lebih unggul daripada jawaban yang diterima karena tidak memperkenalkan beberapa transformasi ajaib dan tidak memerlukan pengguna layanan tambahan. Terima kasih!
Tn. Bungle
23

Masalahnya adalah format string JSON, Anda dapat menggunakan string URL sederhana dalam data:

$http({
    method: 'POST',
    url: url,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    data: 'username='+$scope.userName+'&password='+$scope.password
}).success(function () {});
moices
sumber
7
Anda harus menggunakan encodeURIComponent($scope.userName)untuk menyandikan url data atau parameter Anda akan rusak jika pengguna memasukkan nilai seperti"&myCustomParam=1"
Ivan Hušnjak
2
ini satu-satunya jawaban yang berhasil bagi saya! Saya melewatkan kesuksesan, tetapi format $ http bagus
xenteros
4

Inilah yang seharusnya (dan tolong jangan ada perubahan backend ... tentu saja tidak ... jika front stack Anda tidak mendukung application/x-www-form-urlencoded, maka buanglah ... semoga AngularJS melakukannya!

$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
 });

Bekerja seperti pesona dengan AngularJS 1.5

Teman-teman, mari beri kamu beberapa saran:

  • gunakan janji .then(success, error)ketika berurusan dengan $http, lupakan .sucessdan .errorpanggilan balik (karena mereka sudah ditinggalkan)

  • Dari situs angularjs di sini " Anda tidak dapat lagi menggunakan string JSON_CALLBACK sebagai pengganti untuk menentukan ke mana nilai parameter panggilan balik harus pergi. "

Jika model data Anda lebih kompleks daripada hanya nama pengguna dan kata sandi, Anda masih bisa melakukan itu (seperti yang disarankan di atas)

$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
});

Dokumen untuk encodeURIComponentdapat ditemukan di sini

Mahieddine M. Ichir
sumber
3

Jika itu bentuk coba ubah tajuk menjadi:

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

dan jika itu bukan formulir dan json sederhana maka coba tajuk ini:

headers[ "Content-type" ] = "application/json";
V31
sumber
Tidak menerima apa pun. Saya masih menerima $_POSTarray kosong .!
Veer Shrivastav
Apakah panggilan $ http ini di controller Anda?
V31
satu hal lagi adalah server end php Anda?
V31
Saya telah menemukan solusi untuk hal yang sama apakah Anda masih mendapatkan masalah @ Vir?
V31
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);
});
pengguna8483090
sumber
4
Jawaban hanya kode tidak berguna untuk komunitas. Silakan lihat Cara Menjawab
abpatil
1

Dari $ http docs ini seharusnya berfungsi ..

  $http.post(url, data,{headers: {'Content-Type': 'application/x-www-form-urlencoded'}})
    .success(function(response) {
         // your code...
     });
Srinath
sumber
@Kevin saya tidak yakin tentang ini tapi..sekali ketika saya mencoba mengirim string itu menunjukkan saya kesalahan
Srinath
@KevinB Baik..Saya mengerti..saya pikir header perlu diubah saat mengirim string .. stackoverflow.com/a/20276775/2466168
Srinath
1
Perhatikan bahwa pengiriman yang benar headerstidak akan memengaruhi datayang masih perlu di-urlencode, dengan satu atau lain cara.
Boaz
data masih dikirim dalam json Anda harus menyandikan data ke dalam x-www-form-urlencoded hanya menambahkan header tidak cukup
wendellmva
1

Anda perlu memposting objek javascript biasa, tidak ada yang lain

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

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

jika Anda memiliki php sebagai back-end maka Anda perlu melakukan beberapa modifikasi lagi .. periksa tautan ini untuk memperbaiki sisi server php

Harishr
sumber
itu persis BUKAN apa yang dia minta, dia secara khusus bertanya bagaimana dia bisa mendapatkannya sebagai x-www-form-urlencoded, karena dia mengalami masalah dengan hal-hal json yang diposting.
ppetermann
@ppetermann Anda sudah memeriksa riwayat sunting pertanyaan sebelum downvoting ..
harishr
1

Meskipun jawaban terlambat, saya menemukan UrlSearchParams sudut bekerja sangat baik bagi saya, itu mengurus pengodean parameter juga.

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();
vanval
sumber
0

Ini berhasil untuk saya. Saya menggunakan sudut untuk front-end dan php laravel untuk back-end. Dalam proyek saya, web sudut mengirim data json ke back-end laravel.

Ini adalah pengontrol sudut saya.

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);
        });

});

Ini adalah pengendali php back-end laravel saya.

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

Ini adalah routing laravel saya

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

Hasil dalam browser adalah

status 200
data JSON_CALLBACK ({"nama pengguna": "Victoria", "kata sandi": "kata sandi", "panggilan balik": "JSON_CALLBACK"}); httpTesting.js: 18 fungsi header (c) {a || (a = sc (b)); mengembalikan c? a [K (c)] || null: a}

Ada ekstensi chrome yang disebut tukang pos. Anda dapat menggunakan untuk menguji url back-end Anda apakah berfungsi atau tidak. https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=id

semoga jawaban saya akan membantu anda.

meazuri
sumber