Come posso pubblicare i dati del modulo urlencoded con $ http senza jQuery?


195

Sono nuovo di AngularJS e, per cominciare, ho pensato di sviluppare una nuova applicazione usando solo AngularJS.

Sto cercando di effettuare una chiamata AJAX sul lato server, utilizzando $httpdalla mia app angolare.

Per l'invio dei parametri, ho provato quanto segue:

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

Funziona, ma usa anche jQuery su $.param. Per rimuovere la dipendenza da jQuery, ho provato:

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

ma questo sembrava fallire. Poi ho provato params:

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

ma anche questo sembrava fallire. Poi ho provato JSON.stringify:

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

Ho trovato queste possibili risposte alla mia ricerca, ma non ho avuto successo. Sto facendo qualcosa di sbagliato? Sono sicuro, AngularJS fornirebbe questa funzionalità, ma come?


Non so quale sia il vero problema, ma ci hai provato$http({method: 'post', url: URL, data: {username: $scope.userName, password: $scope.password}});
Mritunjay,

1
Il tuo primo metodo dovrebbe funzionare, è $scope.userNamedefinito? perché non ci hai provato data: data?
Kevin B,

@KevinB: scusa .. ho apportato la modifica corretta.
Veer Shrivastav,

@mritunjay: scusa .. ho fatto la modifica .. stavo provando lo stesso.
Veer Shrivastav,

@Veer ha funzionato o hai ancora problemi?
V31,

Risposte:


409

Penso che devi fare è trasformare i tuoi dati dall'oggetto non in una stringa JSON, ma per urlare i parametri.

Dal blog di Ben Nadel .

Per impostazione predefinita, il servizio $ http trasformerà la richiesta in uscita serializzando i dati come JSON e quindi pubblicandoli con il tipo di contenuto "application / json". Quando vogliamo pubblicare il valore come un post FORM, dobbiamo cambiare l'algoritmo di serializzazione e pubblicare i dati con il tipo di contenuto "application / x-www-form-urlencoded".

Esempio da qui .

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

AGGIORNARE

Per utilizzare i nuovi servizi aggiunti con AngularJS V1.4, vedere


41
Grazie per non aver usato JQuery!
OverMars

1
cosa succede se devo inviare dati multipart / form?
Dejell,

2
Finché angolare incorpora jqLite angular.element, puoi semplicementereturn angular.element.param(obj);
Vicario,

4
@Vicary Tieni presente che param () non è implementato in jqLite - code.angularjs.org/1.3.14/docs/api/ng/function/angular.element
Alex Pavlov

1
questo è un altro modo di procedere var obj = {a: 1, b: 2}; Object.keys(obj).reduce(function(p, c) { return p.concat([encodeURIComponent(c) + "=" + encodeURIComponent(obj[c])]); }, []).join('&');
test30

136

Variabili di codifica URL che utilizzano solo i servizi AngularJS

Con AngularJS 1.4 e versioni successive, due servizi possono gestire il processo di codifica dei dati url per le richieste POST, eliminando la necessità di manipolare i dati con transformRequesto utilizzando dipendenze esterne come jQuery:

  1. $httpParamSerializerJQLike- un serializzatore ispirato a jQuery .param()( consigliato )

  2. $httpParamSerializer - un serializzatore utilizzato dalla stessa Angular per richieste GET

Esempio di utilizzo

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

Guarda una demo più dettagliata di Plunker


Come sono $httpParamSerializerJQLikee $httpParamSerializerdiversi

In generale, sembra $httpParamSerializerutilizzare un formato di codifica URL meno "tradizionale" rispetto a $httpParamSerializerJQLikequando si tratta di strutture di dati complesse.

Ad esempio (ignorando la codifica percentuale delle parentesi):

Codifica di un array

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

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

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

Codifica di un oggetto

{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

Come possiamo usarlo su $ resource all'interno di una fabbrica?
Stilllife

2
Dovrebbe essere $http.({...invece di `$http.post({...
Carlos Granados il

@CarlosGranados Grazie per avermelo notato. Corretto questo errore di battitura qui e nella demo di Plunker.
Boaz,


4
Questa è la risposta specifica di AngularJS che stavo cercando. Vorrei che il poster selezionasse questa come la migliore risposta.
Marty Chang,

61

Tutti questi sembrano eccessivi (o non funzionano) ... basta fare questo:

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

11
Finalmente un po 'di buon senso
jlewkovich,

Questo non invierà la richiesta con un'intestazione del tipo di contenuto errata?
Phil

Ha funzionato per me ... non so quale fosse l'intestazione, ma la richiesta ha funzionato e ha permesso di autenticarsi correttamente. Perché non lo provi e facci sapere.
Serj Sagan,

5
@Phil Immagino che potrebbe dipendere dal server, ho ricevuto una cattiva richiesta, fino a quando non ho aggiunto {headers: {'Content-Type': 'application / x-www-form-urlencoded'}} come argomento di configurazione, o fornitura uso il costruttore $ http (config) come mostra la risposta di moices. In ogni caso, questo è superiore alla risposta accettata poiché non introduce alcuna trasformazione magica e non richiede all'utente un servizio ausiliario. Grazie!
Mr. Bungle,

23

Il problema è il formato stringa JSON, è possibile utilizzare una semplice stringa URL nei dati:

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

7
devi usare encodeURIComponent($scope.userName)per url codificare i dati o i tuoi parametri verranno danneggiati se l'utente inserisce un valore come"&myCustomParam=1"
Ivan Hušnjak

2
questa è l'unica risposta che ha funzionato per me! Ho saltato il successo, ma il formato $ http è buono
xenteros,

4

Ecco come dovrebbe essere (e per favore non cambiare il backend ... certamente no ... se il tuo stack frontale non supporta application/x-www-form-urlencoded, quindi buttalo via ... speriamo che AngularJS lo faccia!

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

Funziona come un fascino con AngularJS 1.5

Gente, lasciate che vi dia qualche consiglio:

  • usare le promesse .then(success, error)quando si ha a che fare $http, dimenticare .sucesse .errorrichiamare (poiché sono deprecati)

  • Dal sito angularjs qui " Non è più possibile utilizzare la stringa JSON_CALLBACK come segnaposto per specificare dove deve andare il valore del parametro callback. "

Se il tuo modello di dati è più complesso di solo un nome utente e una password, puoi comunque farlo (come suggerito sopra)

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

Il documento per il encodeURIComponentpuò essere trovato qui


3

Se è un modulo, prova a modificare l'intestazione in:

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

e se non è un modulo e un semplice json, prova questa intestazione:

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

Non ricevere nulla. Ho ancora ricevuto un $_POSTarray vuoto .!
Veer Shrivastav,

questa chiamata $ http è nel tuo controller?
V31,

un'altra cosa è il tuo server end php?
V31,

Ho trovato una soluzione per lo stesso stai ancora riscontrando il problema @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
Le risposte solo al codice non sono utili per la comunità. Si prega di guardare come rispondere
abpatil

1

Dai documenti $ http dovrebbe funzionare ..

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

@Kevin non ne sono sicuro ma..quando ho provato a inviare una stringa mi ha mostrato un errore
Srinath,

@KevinB Bene..ho capito..penso che le intestazioni debbano essere cambiate durante l'invio di una stringa .. stackoverflow.com/a/20276775/2466168
Srinath

1
Si noti che l'invio del corretto headersnon influirebbe su quello datache dovrà comunque essere urlencoded, in un modo o nell'altro.
Boaz,

i dati vengono ancora inviati in json è necessario codificare i dati in x-www-form-urlencoded solo l'aggiunta di un'intestazione non è sufficiente
wendellmva,

1

devi pubblicare un semplice oggetto javascript, nient'altro

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

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

se si dispone di php come back-end, sarà necessario apportare ulteriori modifiche .. consultare questo collegamento per correggere il lato server php


non è esattamente quello che ha chiesto, ha specificamente chiesto come ottenerli come x-www-form-urlencoded, perché sta incontrando problemi con le cose pubblicate su JSON.
ppetermann,

@ppetermann hai controllato la cronologia delle modifiche della domanda prima di effettuare il downgrade ...
harishr,

1

Sebbene una risposta tardiva, ho scoperto che UrlSearchParams angolare ha funzionato molto bene per me, si occupa anche della codifica dei parametri.

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

Questo ha funzionato per me. Uso angolare per front-end e laravel php per back-end. Nel mio progetto, il web angolare invia i dati json al back-end Laravel.

Questo è il mio controller angolare.

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

});

Questo è il mio controller laravel back-end php.

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

Questo è il mio percorso di laravel

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

Il risultato nel browser è

stato 200
dati JSON_CALLBACK ({"nome utente": "Victoria", "password": "password", "callback": "JSON_CALLBACK"}); httpTesting.js: 18 header headers (c) {a || (a = sc (b)); return c? a [K (c)] || null: a}

C'è un'estensione cromata chiamata postino. Puoi utilizzare per testare l'URL back-end che funzioni o meno. https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en

spero, la mia risposta ti aiuterà.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.