Как отправить данные формы с URL-кодом POST с помощью $ http без jQuery?

Я новичок в AngularJS, и для начала я подумал разработать новое приложение, используя только AngularJS.

Я пытаюсь выполнить вызов AJAX на стороне сервера, используя $http из моего приложения Angular.

Для отправки параметров я попробовал следующее:

$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 предоставит такую ​​возможность, но как?


person Veer Shrivastav    schedule 12.07.2014    source источник
comment
Я не знаю, в чем проблема, но пробовали ли вы это $http({method: 'post', url: URL, data: {username: $scope.userName, password: $scope.password}});   -  person Mritunjay    schedule 12.07.2014
comment
Ваш первый метод должен работать, $scope.userName определено? почему ты не попробовал data: data?   -  person Kevin B    schedule 12.07.2014
comment
@KevinB: извините .. Я правильно отредактировал.   -  person Veer Shrivastav    schedule 12.07.2014
comment
@mritunjay: извините .. Я внес правку .. Я пробовал то же самое.   -  person Veer Shrivastav    schedule 12.07.2014
comment
@Veer, это сработало или у вас все еще есть проблемы?   -  person V31    schedule 12.07.2014
comment
@ V31: Ничего не получилось ... все еще сталкиваюсь с проблемой ... не могли бы вы помочь ..   -  person Veer Shrivastav    schedule 12.07.2014
comment
@VeerShrivastav вы пытаетесь отправить форму?   -  person V31    schedule 13.07.2014
comment
@ V31: да, я отправляю форму .. не совсем форму .. но некоторые текстовые поля и пароли ..   -  person Veer Shrivastav    schedule 14.07.2014


Ответы (11)


Я думаю, вам нужно преобразовать данные из объекта не в строку JSON, а в параметры URL.

Из блога Бена Наделя.

По умолчанию служба $ 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, см.

person allenhwkim    schedule 25.07.2014
comment
Спасибо, что не используете JQuery! - person OverMars; 12.01.2015
comment
что, если мне нужно отправить multipart / form-data? - person Dejell; 13.01.2015
comment
Пока angular встраивает jqLite в angular.element, вы можете просто return angular.element.param(obj); - person Vicary; 26.01.2015
comment
@Vicary Имейте в виду, что param () не реализован в jqLite - code.angularjs.org/1.3.14/docs/api/ng/function/angular.element - person Alex Pavlov; 25.03.2015
comment
@AlexPavlov С какой версии? Я уже довольно давно им пользуюсь. - person Vicary; 25.03.2015
comment
@Vicary Я думаю, что param () никогда не был доступен в jqLite. Скорее всего, у вас есть настоящий jQuery, связанный с зависимостями какой-либо сторонней библиотеки и т. Д., Поэтому он работает для вас. В любом случае, опубликованная мною ссылка предоставляет полный официальный список поддерживаемых функций. - person Alex Pavlov; 25.03.2015
comment
Да, вы правы, пока jQuery загружается до Angular, angular.element будет указывать на него. Поскольку для самого angularjs.org требуется jQuery, люди могут легко это пропустить. - person Vicary; 25.03.2015
comment
которые имеют смысл использовать transformRequest для удаления стиля JSON - person Vasyl; 10.09.2015
comment
да, вам нужно преобразовать json в формат значения формы - person Kerisnarendra; 01.09.2016
comment
это еще один путь var obj = {a: 1, b: 2}; Object.keys(obj).reduce(function(p, c) { return p.concat([encodeURIComponent(c) + "=" + encodeURIComponent(obj[c])]); }, []).join('&'); - person test30; 15.09.2016
comment
Хотя этот ответ работает и кажется правильным, он был написан в 2014 году и сейчас устарел. В Angular 1.4 есть встроенный способ сделать это с помощью $ httpParamSerializer. Ознакомьтесь с ответами ниже, чтобы найти объяснение и пример. - person Tomer; 06.01.2017

Переменные кодирования URL с использованием только сервисов AngularJS

С AngularJS 1.4 и выше две службы могут обрабатывать процесс кодирования URL-адресов для запросов POST, устраняя необходимость манипулировать данными с помощью transformRequest или использования внешних зависимостей, таких как jQuery:

  1. $httpParamSerializerJQLike - сериализатор, вдохновленный .param() jQuery (рекомендуется)

  2. $httpParamSerializer - сериализатор, используемый самим Angular для запросов GET

Пример с $ http ()

$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


Пример с $ http.post ()

$http.post(
    'some/api/endpoint',
    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

Чем $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
person Boaz - CorporateShillExchange    schedule 21.06.2015
comment
Как мы можем использовать это для ресурса $ внутри фабрики? - person stilllife; 09.10.2015
comment
Должно быть $http.({... вместо `$http.post({... - person Carlos Granados; 07.11.2015
comment
@CarlosGranados Спасибо, что заметили. Исправлена ​​эта опечатка здесь и в демонстрации Plunker. - person Boaz - CorporateShillExchange; 07.11.2015
comment
Это отлично сработало после перехода с jQuery на AngularJS. - person zero298; 19.02.2016
comment
Это ответ для AngularJS, который я искал. Я бы хотел, чтобы автор статьи выбрал этот ответ как лучший. - person Marty Chang; 01.05.2016
comment
Я не могу ввести $ httpParamSerializerJQLike или $ httpParamSerializer, я использую AngularJS 1.6.6. Каждый раз, когда я ввожу его в контроллер, я получаю undefined или $http function :( - person Marecky; 28.11.2017
comment
@Marecky Как ты уколаешься? Документация Angular 1.6 не предполагает изменений: https://docs.angularjs.org/api/ng/service/$httpParamSerializerJQLike - person Boaz - CorporateShillExchange; 28.11.2017
comment
@Boaz, Это в TypeScript, я ввожу его примерно так: github.com/gitowiec/ciklum-homework/blob/, но с constructor(protected $httpParamSerializerJQLike, protected $http: angular.IHttpService, protected $q: angular.IQService, protected $timeout: angular.ITimeoutService) - person Marecky; 29.11.2017
comment
Это тоже работает с $http.post()? Я попробовал, но не вышло. Однако, если для $http() и method установлено значение POST, все в порядке. - person user1438038; 06.05.2021
comment
@ user1438038 $http.post() - это сокращенный метод с немного другой подписью. Добавлен пример с подписью аргументов $http.post(), который должен работать аналогично. - person Boaz - CorporateShillExchange; 06.05.2021

Все это выглядит излишним (или не работает) ... просто сделайте следующее:

$http.post(loginUrl, `username=${ encodeURIComponent(username) }` +
                     `&password=${ encodeURIComponent(password) }` +
                     '&grant_type=password'
).success(function (data) {
person Serj Sagan    schedule 24.03.2015
comment
Наконец-то здравый смысл - person jlewkovich; 28.07.2015
comment
Разве это не отправит запрос с неправильным заголовком типа содержимого? - person Phil; 22.07.2016
comment
Это сработало для меня ... не уверен, что это за заголовок, но запрос работал, и он позволил успешно пройти аутентификацию. Почему бы вам не протестировать это и не сообщить нам. - person Serj Sagan; 23.07.2016
comment
@Phil Я предполагаю, что это может зависеть от сервера, у меня плохой запрос, пока я не добавлю {headers: {'Content-Type': 'application / x-www-form-urlencoded'}} в качестве аргумента конфигурации или предоставьте использование конструктор $ http (config), как показывает ответ moices. В любом случае это превосходит принятый ответ, поскольку он не вводит каких-либо магических преобразований и не требует от пользователя некоторой вспомогательной службы. Спасибо! - person Mr. Bungle; 17.11.2016

Проблема заключается в формате строки JSON, вы можете использовать простую строку URL-адреса в данных:

$http({
    method: 'POST',
    url: url,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    data: 'username='+$scope.userName+'&password='+$scope.password
}).success(function () {});
person moices    schedule 04.09.2015
comment
вы должны использовать encodeURIComponent($scope.userName) для URL-кодирования данных, иначе ваши параметры будут повреждены, если пользователь введет значение, подобное "&myCustomParam=1" - person Ivan Hušnjak; 09.09.2015
comment
это единственный ответ, который у меня сработал! Я пропустил успех, но формат $ http подходит - person xenteros; 19.07.2016

Вот как это должно быть (и, пожалуйста, никаких изменений в бэкэнде ... конечно, нет ... если ваш передний стек не поддерживает 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

Народ, позвольте дать вам совет:

  • используйте обещания .then(success, error) при работе с $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 можно найти здесь

person Mahieddine M. Ichir    schedule 11.06.2017

Если это форма, попробуйте изменить заголовок на:

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

и если это не форма, а простой json, попробуйте этот заголовок:

headers[ "Content-type" ] = "application/json";
person V31    schedule 15.07.2014
comment
Ничего не получаю. Я все еще получил пустой массив $_POST.! - person Veer Shrivastav; 20.07.2014
comment
это вызов $ http в вашем контроллере? - person V31; 25.07.2014
comment
еще одна вещь - ваш серверный php? - person V31; 25.07.2014
comment
Я нашел решение той же проблемы, у вас все еще проблема @Veer? - person V31; 29.07.2014

Из документов https://docs.angularjs.org/api/ng/service/$http#post это должно работать ..

  $http.post(url, data,{headers: {'Content-Type': 'application/x-www-form-urlencoded'}})
    .success(function(response) {
         // your code...
     });
person Srinath    schedule 12.07.2014
comment
@Kevin, я не уверен в этом, но ... однажды, когда я попытался отправить строку, она показала мне ошибку - person Srinath; 12.07.2014
comment
@KevinB Хорошо .. Я понял ... Я думаю, что заголовки необходимо изменить при отправке строки .. stackoverflow.com/a/ 20276775/2466168 - person Srinath; 12.07.2014
comment
Обратите внимание, что отправка правильного headers не повлияет на data, который все равно нужно будет закодировать, так или иначе. - person Boaz - CorporateShillExchange; 01.09.2015
comment
данные по-прежнему отправляются в json, вы должны закодировать данные в x-www-form-urlencoded, просто добавления заголовка недостаточно - person wendellmva; 28.02.2016

вам нужно опубликовать простой объект javascript, больше ничего

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

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

если у вас есть php в качестве серверной части, вам нужно будет сделать еще несколько изменений. checkout эта ссылка для исправления на стороне сервера php

person harishr    schedule 27.07.2014
comment
это именно НЕ то, о чем он просил, он специально спросил, как он может получить их как x-www-form-urlencoded, потому что у него возникают проблемы с опубликованными материалами json. - person ppetermann; 16.01.2015
comment
@ppetermann, вы проверили историю редактирования вопроса перед тем, как проголосовать против. - person harishr; 20.01.2015

Несмотря на поздний ответ, я обнаружил, что angular 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();
person vanval    schedule 24.03.2017

Это сработало для меня. Я использую 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);
        });

});

Это мой laravel-контроллер php back-end.

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

Это моя маршрутизация laravel

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

Результат в браузере

статус 200
данные JSON_CALLBACK ({"имя пользователя": "Виктория", "пароль": "пароль", "обратный вызов": "JSON_CALLBACK"}); httpTesting.js: 18 заголовков function (c) {a || (a = sc (b)); return c? a [K (c)] || null: a}

Есть расширение для Chrome под названием почтальон. Вы можете использовать его для проверки своего внутреннего URL-адреса, работает он или нет. https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en

надеюсь, мой ответ вам поможет.

person meazuri    schedule 29.07.2014

person    schedule
comment
Ответы только на код бесполезны для сообщества. См. Как ответить - person abpatil; 18.08.2017