javascript - multiple - post with angularjs
AngularJS: ¿Hay alguna forma de que $ http.post envíe parámetros de solicitud en lugar de JSON? (12)
Ajuste rápido: para aquellos que tienen problemas con la configuración global de la función transformRequest, aquí está el fragmento que estoy usando para deshacerse de la Cannot read property ''jquery'' of undefined
error Cannot read property ''jquery'' of undefined
:
$httpProvider.defaults.transformRequest = function(data) {
return data != undefined ? $.param(data) : null;
}
Tengo un código viejo que está haciendo una solicitud POSTE de AJAX a través del método de publicación de jQuery y se ve así:
$.post("/foo/bar", requestData,
function(responseData)
{
//do stuff with response
}
requestData
es solo un objeto javascript con algunas propiedades de cadena básicas.
Estoy en el proceso de mover nuestras cosas para usar Angular, y quiero reemplazar esta llamada con $ http.post. Se me ocurrió lo siguiente:
$http.post("/foo/bar", requestData).success(
function(responseData) {
//do stuff with response
}
});
Cuando hice esto, recibí una respuesta de error 500 del servidor. Usando Firebug, encontré que esto envió el cuerpo de la solicitud así:
{"param1":"value1","param2":"value2","param3":"value3"}
El jQuery $.post
exitoso envía el cuerpo así:
param1=value1¶m2=value2¶m3=value3
El punto final al que estoy llegando espera parámetros de solicitud y no JSON. Por lo tanto, mi pregunta es, de todos modos, ¿decirle a $http.post
que envíe el objeto javascript como parámetros de solicitud en lugar de JSON? Sí, sé que podría construir la cadena yo mismo desde el objeto, pero quiero saber si Angular proporciona algo para este fuera de la caja.
Creo que el parámetro params
config no funcionará aquí ya que agrega la cadena a la url en lugar del cuerpo, pero para agregar a lo que Infeligo sugirió aquí hay un ejemplo de la anulación global de una transformación predeterminada (usando jQuery param como ejemplo para convertir los datos en cadena param).
Configure la función global transformRequest:
var app = angular.module(''myApp'');
app.config(function ($httpProvider) {
$httpProvider.defaults.transformRequest = function(data){
if (data === undefined) {
return data;
}
return $.param(data);
}
});
De esta forma, todas las llamadas a $ http.post transformarán automáticamente el cuerpo en el mismo formato de param utilizado por la llamada jQuery $.post
.
Tenga en cuenta que también puede querer configurar el encabezado de tipo de contenido por llamada o de forma global como este:
$httpProvider.defaults.headers.post[''Content-Type''] = ''application/x-www-form-urlencoded; charset=UTF-8'';
Sample transformRequest no global por llamada:
var transform = function(data){
return $.param(data);
}
$http.post("/foo/bar", requestData, {
headers: { ''Content-Type'': ''application/x-www-form-urlencoded; charset=UTF-8''},
transformRequest: transform
}).success(function(responseData) {
//do stuff with response
});
De la documentación de AngularJS:
params - {Object.} - Mapa de cadenas u objetos que se convertirán en? key1 = value1 & key2 = value2 después de la url. Si el valor no es una cadena , será JSONified.
Por lo tanto, proporcione cadena como parámetros. Si no quieres eso, entonces usa transformaciones. Nuevamente, de la documentación:
Para anular estas transformaciones localmente, especifique las funciones de transformación como las propiedades transformRequest y / o transformResponse del objeto config. Para anular globalmente las transformaciones predeterminadas, anule las propiedades $ httpProvider.defaults.transformRequest y $ httpProvider.defaults.transformResponse del $ httpProvider.
Consulte la documentation para más detalles.
Encontré muchas veces el comportamiento problemático de este todo. Lo usé de expreso (sin typings) y bodyParser (con el dt ~ body-parser typings).
No intenté subir un archivo, sino simplemente interpretar un JSON dado en una cadena de publicaciones.
El request.body
era simplemente un json vacío ( {}
).
Después de mucha investigación, finalmente, esto funcionó para mí:
import { json } from ''body-parser'';
...
app.use(json()); <-- should be defined before the first POST handler!
También puede ser importante dar el tipo de contenido application/json
en la cadena de solicitud desde el lado del cliente.
Esto podría ser algo así como un hack, pero evité el problema y convertí el json en el arreglo POST de PHP en el lado del servidor:
$_POST = json_decode(file_get_contents(''php://input''), true);
Modificar los encabezados predeterminados:
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8";
Luego use el método $.param
JQuery:
var payload = $.param({key: value});
$http.post(targetURL, payload);
Si utilizo Angular> = 1.4 , aquí está la solución más limpia que he encontrado que no depende de nada personalizado o externo:
angular.module(''yourModule'')
.config(function ($httpProvider, $httpParamSerializerJQLikeProvider){
$httpProvider.defaults.transformRequest.unshift($httpParamSerializerJQLikeProvider.$get());
$httpProvider.defaults.headers.post[''Content-Type''] = ''application/x-www-form-urlencoded; charset=utf-8'';
});
Y luego puedes hacer esto en cualquier lugar de tu aplicación:
$http({
method: ''POST'',
url: ''/requesturl'',
data: {
param1: ''value1'',
param2: ''value2''
}
});
Y serializará correctamente los datos como param1=value1¶m2=value2
y lo enviará a /requesturl
con la application/x-www-form-urlencoded; charset=utf-8
application/x-www-form-urlencoded; charset=utf-8
Content-Type header como normalmente se espera con solicitudes POST en puntos finales.
También puede resolver este problema sin cambiar el código en el servidor, cambiar el encabezado en la llamada $http.post
y usar $_POST
la manera habitual. Explicado aquí: http://victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax/
También tengo problemas para configurar la autenticación HTTP personalizada porque $ resource almacena en caché la solicitud.
Para que funcione, debes sobrescribir los encabezados existentes haciendo esto
var transformRequest = function(data, headersGetter){
var headers = headersGetter();
headers[''Authorization''] = ''WSSE profile="UsernameToken"'';
headers[''X-WSSE''] = ''UsernameToken '' + nonce
headers[''Content-Type''] = ''application/json'';
};
return $resource(
url,
{
},
{
query: {
method: ''POST'',
url: apiURL + ''/profile'',
transformRequest: transformRequest,
params: {userId: ''@userId''}
},
}
);
Espero poder ayudar a alguien Me llevó 3 días resolver esto.
Tenga en cuenta que a partir de Angular 1.4, puede serializar los datos del formulario sin utilizar jQuery.
En la aplicación.js:
module.run(function($http, $httpParamSerializerJQLike) {
$http.defaults.transformRequest.unshift($httpParamSerializerJQLike);
});
Luego en tu controlador:
$http({
method: ''POST'',
url: myUrl'',
headers: {''Content-Type'': ''application/x-www-form-urlencoded''},
data: myData
});
Use la función $.param
jQuery para serializar los datos JSON en requestData.
En resumen, usando un código similar al tuyo:
$http.post("/foo/bar",
$.param(requestData),
{
headers:
{
''Content-Type'': ''application/x-www-form-urlencoded; charset=UTF-8''
}
}
).success(
function(responseData) {
//do stuff with response
}
});
Para usar esto, debe incluir jQuery en su página junto con AngularJS.
.controller(''pieChartController'', [''$scope'', ''$http'', ''$httpParamSerializerJQLike'', function($scope, $http, $httpParamSerializerJQLike) {
var data = {
TimeStamp : "2016-04-25 12:50:00"
};
$http({
method: ''POST'',
url: ''serverutilizationreport'',
headers: {''Content-Type'': ''application/x-www-form-urlencoded''},
data: $httpParamSerializerJQLike(data),
}).success(function () {});
}
]);