Wie poste ich urlencodierte Formulardaten mit $ http ohne jQuery?

195

Ich bin neu in AngularJS und dachte zunächst daran, eine neue Anwendung nur mit AngularJS zu entwickeln.

Ich versuche, über $httpmeine Angular-App einen AJAX-Anruf auf der Serverseite zu tätigen .

Zum Senden der Parameter habe ich Folgendes versucht:

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

Dies funktioniert, aber es wird auch jQuery bei verwendet $.param. Um die Abhängigkeit von jQuery zu entfernen, habe ich versucht:

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

aber das schien zu scheitern. Dann habe ich versucht params:

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

aber das schien auch zu scheitern. Dann habe ich versucht JSON.stringify:

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

Ich fand diese möglichen Antworten auf meine Suche, war aber erfolglos. Mache ich etwas falsch? Ich bin sicher, AngularJS würde diese Funktionalität bereitstellen, aber wie?

Veer Shrivastav
quelle
Ich weiß nicht, was das eigentliche Problem ist, aber haben Sie dies versucht$http({method: 'post', url: URL, data: {username: $scope.userName, password: $scope.password}});
Mritunjay
1
Ihre erste Methode sollte funktionieren, ist $scope.userNamedefiniert? Warum hast du es nicht versucht data: data?
Kevin B
@ KevinB: Entschuldigung. Ich habe die richtige Bearbeitung vorgenommen.
Veer Shrivastav
@mritunjay: Entschuldigung .. Ich habe die Bearbeitung vorgenommen .. Ich habe das gleiche versucht.
Veer Shrivastav
@Veer hat es funktioniert oder hast du immer noch Probleme?
V31

Antworten:

409

Ich denke, Sie müssen Ihre Daten vom Objekt nicht in eine JSON-Zeichenfolge, sondern in URL-Parameter umwandeln.

Aus dem Blog von Ben Nadel .

Standardmäßig transformiert der $ http-Dienst die ausgehende Anforderung, indem er die Daten als JSON serialisiert und dann mit dem Inhaltstyp "application / json" veröffentlicht. Wenn wir den Wert als FORM-Beitrag veröffentlichen möchten, müssen wir den Serialisierungsalgorithmus ändern und die Daten mit dem Inhaltstyp "application / x-www-form-urlencoded" veröffentlichen.

Beispiel von hier .

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

AKTUALISIEREN

Informationen zum Verwenden neuer Dienste, die mit AngularJS V1.4 hinzugefügt wurden, finden Sie unter

allenhwkim
quelle
41
Vielen Dank, dass Sie JQuery nicht verwenden!
OverMars
1
Was ist, wenn ich mehrteilige / Formulardaten einreichen muss?
Dejell
2
Solange eckig jqLite unter einbettet angular.element, können Sie einfachreturn angular.element.param(obj);
Vicary
4
@Vicary Beachten Sie, dass param () nicht in jqLite implementiert ist - code.angularjs.org/1.3.14/docs/api/ng/function/angular.element
Alex Pavlov
1
Dies ist ein weiterer Weg zu gehen var obj = {a: 1, b: 2}; Object.keys(obj).reduce(function(p, c) { return p.concat([encodeURIComponent(c) + "=" + encodeURIComponent(obj[c])]); }, []).join('&');
Test30
136

URL-Codierungsvariablen, die nur AngularJS-Dienste verwenden

Mit AngularJS 1.4 und höher können zwei Dienste den Prozess der URL-Codierung von Daten für POST-Anforderungen übernehmen, sodass keine Daten mit transformRequestoder mit externen Abhängigkeiten wie jQuery bearbeitet werden müssen :

  1. $httpParamSerializerJQLike- ein von jQuery's inspirierter Serializer .param()( empfohlen )

  2. $httpParamSerializer - Ein Serializer, der von Angular selbst für GET-Anforderungen verwendet wird

Anwendungsbeispiel

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

Sehen Sie sich eine ausführlichere Plunker-Demo an


Wie $httpParamSerializerJQLikeund $httpParamSerializeranders

Im Allgemeinen scheint es $httpParamSerializerweniger "traditionelles" URL-Codierungsformat zu verwenden als $httpParamSerializerJQLikebei komplexen Datenstrukturen.

Zum Beispiel (Ignorieren der prozentualen Codierung von Klammern):

Codierung eines Arrays

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

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

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

Codieren eines Objekts

{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
quelle
Wie können wir dies für $ resource in einer Fabrik verwenden?
Stillleben
2
Sollte $http.({...statt sein$http.post({...
Carlos Granados
@CarlosGranados Danke, dass du es bemerkt hast. Dieser Tippfehler wurde hier und in der Plunker-Demo korrigiert.
Boaz
Dies funktionierte perfekt nach der Migration von jQuery nach AngularJS
zero298
4
Dies ist die AngularJS-spezifische Antwort, nach der ich gesucht habe. Ich wünschte, das Poster würde dies als beste Antwort auswählen.
Marty Chang
61

All dies sieht nach Overkill aus (oder funktioniert nicht) ... machen Sie einfach Folgendes:

$http.post(loginUrl, `username=${ encodeURIComponent(username) }` +
                     `&password=${ encodeURIComponent(password) }` +
                     '&grant_type=password'
).success(function (data) {
Serj Sagan
quelle
11
Endlich ein
gesunder
Wird die Anfrage nicht mit dem falschen Header vom Inhaltstyp gesendet?
Phil
Es hat bei mir funktioniert ... ich bin mir nicht sicher, was der Header war, aber die Anfrage hat funktioniert und es konnte erfolgreich authentifiziert werden. Probieren Sie es aus und lassen Sie es uns wissen.
Serj Sagan
5
@Phil Ich denke, es könnte vom Server abhängen, ich habe eine schlechte Anfrage erhalten, bis ich {Header: {'Content-Type': 'application / x-www-form-urlencoded'}} als Konfigurationsargument hinzugefügt oder die Verwendung angegeben habe Der Konstruktor $ http (config) zeigt die Antwort von moices. In beiden Fällen ist dies der akzeptierten Antwort überlegen, da keine magische Transformation eingeführt wird und der Benutzer keinen zusätzlichen Dienst benötigt. Vielen Dank!
Mr. Bungle
23

Das Problem ist das JSON-Zeichenfolgenformat. Sie können eine einfache URL-Zeichenfolge in Daten verwenden:

$http({
    method: 'POST',
    url: url,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    data: 'username='+$scope.userName+'&password='+$scope.password
}).success(function () {});
Moices
quelle
7
Sie müssen verwenden encodeURIComponent($scope.userName), um die Daten per URL zu codieren, oder Ihre Parameter werden beschädigt, wenn der Benutzer einen Wert wie"&myCustomParam=1"
Ivan Hušnjak
2
Dies ist die einzige Antwort, die für mich funktioniert hat! Ich habe den Erfolg übersprungen, aber das $ http-Format ist gut
xenteros
4

Hier ist, wie es sein sollte (und bitte keine Änderungen am Backend ... schon gar nicht ... wenn Ihr Frontstack nicht unterstützt application/x-www-form-urlencoded, dann werfen Sie es weg ... hoffentlich 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
 });

Funktioniert wie ein Zauber mit AngularJS 1.5

Leute, lasst euch einen Rat geben:

  • Verwenden Sie Versprechen .then(success, error)beim Umgang mit $http, Vergessen .sucessund .errorRückrufen (da diese veraltet sind).

  • Von der Website anglejs hier " Sie können die Zeichenfolge JSON_CALLBACK nicht mehr als Platzhalter verwenden, um anzugeben, wohin der Wert des Rückrufparameters gehen soll. "

Wenn Ihr Datenmodell komplexer ist als nur ein Benutzername und ein Passwort, können Sie dies trotzdem tun (wie oben vorgeschlagen).

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

Dokument für die encodeURIComponentfinden Sie hier

Mahieddine M. Ichir
quelle
3

Wenn es sich um ein Formular handelt, ändern Sie den Header in:

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

und wenn es kein Formular und kein einfacher JSON ist, versuchen Sie diesen Header:

headers[ "Content-type" ] = "application/json";
V31
quelle
Nichts erhalten. Ich habe immer noch ein leeres $_POSTArray erhalten.!
Veer Shrivastav
Ist dieser $ http-Aufruf in Ihrem Controller?
V31
eine weitere Sache ist Ihr Server Ende PHP?
V31
Ich habe eine Lösung für das gleiche gefunden. Bekommst du immer noch das Problem @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);
});
user8483090
quelle
4
Nur-Code-Antworten sind für die Community nicht nützlich. Bitte schauen Sie, wie zu
antworten
1

Von den $ http- Dokumenten sollte dies funktionieren.

  $http.post(url, data,{headers: {'Content-Type': 'application/x-www-form-urlencoded'}})
    .success(function(response) {
         // your code...
     });
Srinath
quelle
@ Kevin Ich bin mir nicht sicher, aber ... einmal, als ich versuchte, einen String zu senden, zeigte es mir einen Fehler
Srinath
@ KevinB Fein. Ich habe es verstanden. Ich denke, Header müssen beim Senden eines Strings geändert werden. Stackoverflow.com/a/20276775/2466168
Srinath
1
Beachten Sie, dass das Senden des korrekten Datums headerskeine Auswirkungen auf das hat, datawas auf die eine oder andere Weise noch urlencodiert werden muss.
Boaz
Daten werden immer noch in JSON gesendet. Sie müssen die Daten in x-www-form-urlencoded codieren. Das Hinzufügen eines Headers reicht nicht aus
wendellmva
1

Sie müssen ein einfaches Javascript-Objekt posten, sonst nichts

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

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

Wenn Sie PHP als Back-End haben, müssen Sie weitere Änderungen vornehmen. Schauen Sie sich diesen Link an, um die PHP-Serverseite zu reparieren

harishr
quelle
das ist genau NICHT das, wonach er gefragt hat, er hat speziell gefragt, wie er sie als x-www-form-urlencoded bekommen kann, weil er auf Probleme mit geposteten JSON-Sachen stößt.
ppetermann
@ppetermann haben Sie den Bearbeitungsverlauf der Frage vor dem Downvoting überprüft ..
Harishr
1

Obwohl eine späte Antwort, fand ich, dass eckige UrlSearchParams für mich sehr gut funktionierten, kümmert es sich auch um die Codierung von Parametern.

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
quelle
0

Das hat bei mir funktioniert. Ich benutze eckig für Front-End und Laravel PHP für Back-End. In meinem Projekt sendet Angular Web JSON-Daten an das Laravel-Backend.

Das ist mein Winkelregler.

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

});

Dies ist mein PHP-Backend-Laravel-Controller.

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

Dies ist mein Laravel-Routing

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

Das Ergebnis im Browser ist

Status 200
Daten JSON_CALLBACK ({"Benutzername": "Victoria", "Passwort": "Passwort", "Rückruf": "JSON_CALLBACK"}); httpTesting.js: 18 Header-Funktion (c) {a || (a = sc (b)); Rückgabe c? a [K (c)] || null: a}

Es gibt eine Chrom-Erweiterung namens Postman. Sie können damit Ihre Back-End-URL testen, ob sie funktioniert oder nicht. https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=de

Hoffentlich hilft Ihnen meine Antwort.

Meazuri
quelle