Làm cách nào để tôi POST dữ liệu biểu mẫu được mã hóa bằng $ http mà không có jQuery?


195

Tôi chưa quen với AngularJS và để bắt đầu, tôi đã nghĩ sẽ phát triển một ứng dụng mới chỉ sử dụng AngularJS.

Tôi đang cố gắng thực hiện cuộc gọi AJAX đến phía máy chủ, sử dụng $httptừ Ứng dụng Angular của tôi.

Để gửi các tham số, tôi đã thử như sau:

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

Điều này đang hoạt động, nhưng nó cũng đang sử dụng jQuery $.param. Để loại bỏ sự phụ thuộc vào jQuery, tôi đã thử:

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

nhưng điều này dường như thất bại. Sau đó tôi đã thử params:

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

nhưng điều này dường như cũng thất bại. Sau đó tôi đã thử JSON.stringify:

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

Tôi tìm thấy những câu trả lời có thể cho nhiệm vụ của mình, nhưng không thành công. Tôi có làm điều gì sai? Tôi chắc chắn, AngularJS sẽ cung cấp chức năng này, nhưng bằng cách nào?


Tôi không biết vấn đề thực sự là gì nhưng bạn đã thử điều này chưa$http({method: 'post', url: URL, data: {username: $scope.userName, password: $scope.password}});
Mritunjay

1
Phương pháp đầu tiên của bạn nên làm việc, được $scope.userNamexác định? tại sao bạn không thử data: data?
Kevin B

@KevinB: xin lỗi .. tôi đã chỉnh sửa chính xác.
Veer Shrivastav

@mritunjay: xin lỗi .. tôi đã thực hiện chỉnh sửa .. Tôi đã cố gắng như vậy.
Veer Shrivastav

@Veer đã làm việc hay bạn vẫn gặp vấn đề?
V31

Câu trả lời:


409

Tôi nghĩ bạn cần làm là chuyển đổi dữ liệu của mình từ đối tượng không thành chuỗi JSON, mà thành các thông số url.

Từ blog của Ben Nadel .

Theo mặc định, dịch vụ $ http sẽ chuyển đổi yêu cầu gửi đi bằng cách tuần tự hóa dữ liệu dưới dạng JSON và sau đó đăng nó với loại nội dung, "application / json". Khi chúng tôi muốn đăng giá trị dưới dạng bài đăng FORM, chúng tôi cần thay đổi thuật toán tuần tự hóa và đăng dữ liệu với kiểu nội dung, "application / x-www-form-urlencoding".

Ví dụ từ đây .

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

CẬP NHẬT

Để sử dụng các dịch vụ mới được thêm vào với AngularJS V1.4, hãy xem


41
Cảm ơn bạn đã không sử dụng JQuery!
OverMars

1
Nếu tôi cần gửi nhiều dữ liệu / biểu mẫu dữ liệu thì sao?
Dejell

2
Miễn là góc cạnh nhúng jqLite bên dưới angular.element, bạn có thể chỉ cầnreturn angular.element.param(obj);
Vicary

4
@Vicary Hãy nhớ rằng param () không được triển khai trong jqLite - code.angularjs.org/1.3.14/docs/api/ng/feft/angular.element
Alex Pavlov

1
đây là một cách khác để đi var obj = {a: 1, b: 2}; Object.keys(obj).reduce(function(p, c) { return p.concat([encodeURIComponent(c) + "=" + encodeURIComponent(obj[c])]); }, []).join('&');
test30

136

Biến mã hóa URL chỉ sử dụng dịch vụ AngularJS

Với AngularJS 1.4 trở lên, hai dịch vụ có thể xử lý quá trình dữ liệu mã hóa url cho các yêu cầu POST, loại bỏ nhu cầu thao tác dữ liệu với transformRequesthoặc sử dụng các phụ thuộc bên ngoài như jQuery:

  1. $httpParamSerializerJQLike- một serializer lấy cảm hứng từ jQuery .param()(được khuyến nghị )

  2. $httpParamSerializer - một serializer được sử dụng bởi chính Angular cho các yêu cầu GET

Ví dụ sử dụng

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

Xem bản demo Plunker dài dòng hơn


Như thế nào $httpParamSerializerJQLike$httpParamSerializerkhác nhau

Nhìn chung, dường như $httpParamSerializersử dụng định dạng mã hóa url "truyền thống" ít hơn so với $httpParamSerializerJQLikekhi nói đến cấu trúc dữ liệu phức tạp.

Ví dụ: (bỏ qua phần trăm mã hóa của ngoặc):

Mã hóa một mảng

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

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

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

Mã hóa một đối tượng

{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

Làm thế nào chúng ta có thể sử dụng điều này trên $ resource trong một nhà máy?
tĩnh vật

2
Nên $http.({...thay vì `$http.post({...
Carlos Granados

@CarlosGranados Cảm ơn bạn đã chú ý. Sửa lỗi đánh máy này ở đây và trong bản demo Plunker.
Boaz

Điều này hoạt động hoàn hảo sau khi di chuyển từ jQuery sang AngularJS
zero298

4
Đây là câu trả lời dành riêng cho AngularJS mà tôi đang tìm kiếm. Tôi muốn người đăng sẽ chọn đây là câu trả lời tốt nhất.
Marty Chang

61

Tất cả những thứ này trông giống như quá mức cần thiết (hoặc không hoạt động) ... chỉ cần làm điều này:

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

11
Cuối cùng, một số ý nghĩa thông thường
jlewkovich

Điều này sẽ không gửi yêu cầu với tiêu đề loại nội dung sai?
Phil

Nó hoạt động với tôi ... không chắc tiêu đề là gì, nhưng yêu cầu đã hoạt động và nó cho phép xác thực thành công. Tại sao bạn không kiểm tra nó và cho chúng tôi biết.
Serj Sagan

5
@Phil Tôi đoán nó có thể phụ thuộc vào máy chủ, tôi nhận được yêu cầu xấu, cho đến khi tôi thêm {headers: {'Content-Type': 'application / x-www-form-urlencoding'}} làm cấu hình arg hoặc sử dụng cung cấp hàm tạo $ http (config) như câu trả lời của moices hiển thị. Dù bằng cách nào thì điều này cũng vượt trội hơn câu trả lời được chấp nhận vì nó không đưa ra một số phép biến đổi và không yêu cầu người sử dụng một số dịch vụ phụ trợ. Cảm ơn!
Ông Bungle

23

Vấn đề là định dạng chuỗi JSON, Bạn có thể sử dụng chuỗi URL đơn giản trong dữ liệu:

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

7
bạn phải sử dụng encodeURIComponent($scope.userName)để mã hóa url dữ liệu nếu không các tham số của bạn sẽ bị hỏng nếu người dùng nhập giá trị như"&myCustomParam=1"
Ivan Hušnjak

2
đây là câu trả lời duy nhất có hiệu quả với tôi Tôi đã bỏ qua thành công, nhưng định dạng $ http là tốt
xenteros

4

Đây là cách nó phải như vậy (và xin vui lòng không thay đổi phụ trợ ... chắc chắn là không ... nếu ngăn xếp trước của bạn không hỗ trợ application/x-www-form-urlencoded, thì hãy vứt nó đi ... hy vọng AngularJS sẽ làm được!

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

Hoạt động như một bùa mê với AngularJS 1.5

Mọi người, hãy cho bạn một lời khuyên:

  • sử dụng lời hứa .then(success, error)khi giao dịch $http, quên .sucess.errorgọi lại (vì chúng không được dùng nữa)

  • Từ trang angularjs tại đây " Bạn không còn có thể sử dụng chuỗi JSON_CALLBACK làm trình giữ chỗ để chỉ định giá trị tham số gọi lại sẽ đi đâu. "

Nếu mô hình dữ liệu của bạn phức tạp hơn chỉ cần tên người dùng và mật khẩu, bạn vẫn có thể làm điều đó (như được đề xuất ở trên)

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

Tài liệu cho encodeURIComponentcó thể được tìm thấy ở đây


3

Nếu nó là một hình thức hãy thử thay đổi tiêu đề thành:

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

và nếu nó không phải là một hình thức và một json đơn giản thì hãy thử tiêu đề này:

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

Không nhận được gì. Tôi vẫn nhận được $_POSTmảng trống .!
Veer Shrivastav

cuộc gọi $ http này trong bộ điều khiển của bạn phải không?
V31

Một điều nữa là máy chủ của bạn kết thúc php?
V31

Tôi đã tìm thấy một giải pháp tương tự là bạn vẫn gặp phải vấn đề @Veer?
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);
});

4
Mã chỉ trả lời không hữu ích cho cộng đồng. Vui lòng xem Cách trả lời
abpatil

1

Từ các tài liệu $ http, điều này sẽ hoạt động ..

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

@Kevin Tôi không chắc về điều này nhưng..thì khi tôi thử gửi một chuỗi nó đã cho tôi thấy một lỗi
Srinath

@KevinB Fine..Tôi hiểu rồi..tôi nghĩ cần phải thay đổi tiêu đề trong khi gửi một chuỗi .. stackoverflow.com/a/20276775/2466168
Srinath

1
Lưu ý rằng việc gửi chính xác headerssẽ không ảnh hưởng đến việc datavẫn sẽ cần phải được mã hóa bằng cách này hay cách khác.
Boaz

dữ liệu vẫn được gửi trong json, bạn phải mã hóa dữ liệu thành x-www-form-urlencoding chỉ thêm một tiêu đề là không đủ
wendellmva

1

bạn cần đăng đối tượng javascript đơn giản, không có gì khác

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

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

Nếu bạn có php là back-end thì bạn sẽ cần phải sửa đổi thêm .. hãy kiểm tra liên kết này để sửa lỗi phía máy chủ php


đó chính xác KHÔNG phải là những gì anh ta yêu cầu, anh ta đặc biệt hỏi làm thế nào anh ta có thể lấy chúng dưới dạng x-www-form-urlencoding, bởi vì anh ta đang gặp vấn đề với những thứ json được đăng.
ppetermann

@ppetermann bạn đã kiểm tra lịch sử chỉnh sửa của câu hỏi trước khi hạ cấp ..
harishr

1

Mặc dù câu trả lời muộn, tôi thấy UrlSearchParams góc cạnh hoạt động rất tốt đối với tôi, nó cũng đảm nhiệm việc mã hóa các tham số.

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

Điều này làm việc cho tôi. Tôi sử dụng angular cho front-end và laravel php cho back-end. Trong dự án của tôi, web góc gửi dữ liệu json đến back-end laravel.

Đây là bộ điều khiển góc của tôi.

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

});

Đây là bộ điều khiển laravel back-end php của tôi.

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

Đây là định tuyến laravel của tôi

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

Kết quả trong trình duyệt là

trạng thái 200
dữ liệu JSON_CALLBACK ({"tên người dùng": "Victoria", "mật khẩu": "mật khẩu", "gọi lại": "JSON_CALLBACK"}); httpTesting.js: Hàm 18 tiêu đề (c) {a || (a = sc (b)); return c? a [K (c)] | | null: a}

Có phần mở rộng chrome được gọi là postman. Bạn có thể sử dụng để kiểm tra url back-end của mình xem nó có hoạt động hay không. https://chrom.google.com.vn/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=vi

Hy vọng, câu trả lời của tôi sẽ giúp bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.