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


195

Я новичок в 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 обеспечит эту функциональность, но как?


Я не знаю, что является реальной проблемой, но вы попробовали это$http({method: 'post', url: URL, data: {username: $scope.userName, password: $scope.password}});
Mritunjay

1
Ваш первый метод должен работать, $scope.userNameопределен? почему ты не попробовал data: data?
Кевин Б.

@KevinB: извините .. Я сделал правильное редактирование.
Веер Шривастав,

@mritunjay: извините .. Я внес изменения .. Я пытался то же самое.
Веер Шривастав,

@ Veer это сработало или у тебя все еще есть проблемы?
V31

Ответы:


409

Я думаю, вам нужно преобразовать ваши данные из объекта не в строку 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, см.


41
Спасибо, что не используете JQuery!
OverMars

1
Что делать, если мне нужно отправить multipart / form-data?
Dejell

2
Пока угловое встраивает jqLite angular.element, вы можете простоreturn angular.element.param(obj);
Vicary

4
@Vicary Имейте в виду, что param () не реализован в jqLite - code.angularjs.org/1.3.14/docs/api/ng/function/angular.element
Алекс Павлов

1
это еще один путь var obj = {a: 1, b: 2}; Object.keys(obj).reduce(function(p, c) { return p.concat([encodeURIComponent(c) + "=" + encodeURIComponent(obj[c])]); }, []).join('&');
test30

137

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

Начиная с версии AngularJS 1.4 и выше, две службы могут обрабатывать процесс кодирования данных url для запросов POST, устраняя необходимость манипулировать данными с transformRequestиспользованием или используя внешние зависимости, такие как jQuery:

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

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

Пример использования

$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

Как мы можем использовать это на $ ресурсе внутри фабрики?
Натюрморт

2
Должно быть $http.({...вместо`$http.post({...
Карлос Гранадос

@CarlosGranados Спасибо, что заметили. Исправлена ​​эта опечатка здесь и в демоверсии Plunker.
Вооз

Это отлично работало после перехода с jQuery на AngularJS
zero298

4
Это специфичный для AngularJS ответ, который я искал. Я хотел бы, чтобы плакат выбрал это как лучший ответ.
Марти Чанг

61

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

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

11
Наконец , некоторые здравый смысл
jlewkovich

Разве это не отправит запрос с неправильным заголовком типа контента?
Фил

Он работал для меня ... не уверен, что заголовок был, но запрос работал, и это позволило успешно аутентифицироваться. Почему бы вам не проверить это и сообщить нам.
Серж Саган

5
@Phil Я думаю, это может зависеть от сервера, я получил неверный запрос, пока не добавил {headers: {'Content-Type': 'application / x-www-form-urlencoded'}} в качестве аргумента конфигурации или использования предложения $ http (config) конструктор, как показывает ответ moices. В любом случае это превосходит принятый ответ, поскольку он не вводит магического преобразования и не требует от пользователя какого-либо вспомогательного обслуживания. Спасибо!
Мистер Бангла

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"
введет

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

Люди, давайте дадим вам несколько советов:

  • использовать обещания .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можно найти здесь


3

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

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

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

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

Ничего не получаю. Я все еще получил пустой $_POSTмассив.
Веер Шривастав

это вызов $ http в вашем контроллере?
V31

еще одна вещь, ваш сервер php?
V31

Я нашел решение для того же, вы все еще получаете проблему @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
Ответы только на код не полезны для сообщества. Пожалуйста, посмотрите на Как ответить
abpatil

1

Из документов $ http это должно работать ..

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

@Kevin Я не уверен в этом, но .. как только я попытался отправить строку, это показало мне ошибку
Srinath

@KevinB Хорошо .. Я понял .. я думаю, что заголовки нужно менять при отправке строки .. stackoverflow.com/a/20276775/2466168
Сринат

1
Обратите внимание, что отправка правильного headersне повлияет на то, dataчто все равно нужно будет кодировать, так или иначе.
Вооз

данные по-прежнему отправляются в формате 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 сервера


это точно НЕ то, что он просил, он специально спросил, как он может получить их как x-www-form-urlencoded, потому что он сталкивается с проблемами с размещенными материалами json.
ppetermann

@ppetermann вы проверили историю редактирования вопроса, прежде чем понизить голосование ..
harishr

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

Это сработало для меня. Я использую угловой для front-end и laravel php для back-end. В моем проекте 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 back-end контроллер 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)); вернуть c? a [K (c)] || null: a}

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.