Is there anyway to tell angularjs ( $http service) not to send some properties into a Json object when doing a HTTP POST?
Let's say that i have an Object definition like this :
$scope.toBeSaved = { id : 1,
name: myname,
someAttributeTobeFiltered : 1233459,
}
Is There anyway to filter the someAttributeTobeFiltered not to be send during a $http.post(url,$scope.toBeSaved) call?
Thanks in advance
This will remove the given property on every request made via $http.
.config(['$httpProvider', function($httpProvider )
{
$httpProvider.defaults.transformRequest = [function(data)
{
if(typeof data === "object")
{
var toSend = angular.copy(data);
delete toSend.someAttributeTobeFiltered;
return toSend;
}
else{
return data;
}
}];
}]);
So using _.omit method you can do following:
$http.post(url, _.omit($scope.toBeSaved, ['someAttributeTobeFiltered', 'foo', 'bar']))
Related
I can't figure out how to URL encode array params in an elegant way, in order to send XHR requests from my Vue.js client to my Symfony PHP API.
For example i have this GET method endpoint:
/question/list?subjects={idSubject}
It lists Question entity items and optionally, accepts params in order to filter results by them (subjects in this case)
The desired one would be:
/question/list?subjects[]={idSubject}&subjects[]={idSubject}
I'm using Axios for Vue.js to perform XHR requests and i created a main class that implements the methods that i want.
As the get() method doesn't support 'data' property in config object, i implemented it at the same way of a POST call and then i process it in order to build the desired URL.
This is my Ajax.js file:
const ajaxRequest = (config) => {
const token = TokenStorage.get()
config.baseURL = '/ajax'
if (token) {
config.headers = {
'Authorization': 'Bearer ' + token
}
}
return Axios.request(config)
}
const Ajax = {
get: (endpoint, params = null, config = {}) => {
const querystring = require('querystring')
let url = endpoint
if (Array.isArray(params) && params.length) {
url += '?' + params.join('&')
} else if (typeof params === 'object' && params !== null && Object.keys(params).length) {
url += '?' + querystring.stringify(params)
}
config = {
...config,
...{
url: url,
method: 'get'
}
}
return ajaxRequest(config)
},
post: (endpoint, params, config = {}) => {
config = {
...config,
...{
url: endpoint,
method: 'post',
data: params
}
}
return ajaxRequest(config)
}
}
I know that I could pass this data by POST but, in order to follow restful design, i want to keep GET method and optional params can be included in the URL as GET params.
If it were me I'd build a JavaScript array then call JSON.stringify() on it... then URL encode the resultant string and attach it as the sole parameter... to be JSON parsed by your server side handler.
I'm in a similar situation and I couln't find a built in library for this.
the most elegant solution I've found so far is by adding
Array.prototype.encodeURI = function(name) {
prefix = `${name}[]=`;
return prefix + this.map(o => encodeURI(o)).join(`&${prefix}`);
}
now you can use it:
let subjects = ["First Subject", "Second Subject"];
let myquery = subjects.encodeURI("subjects")
console.log(myquery)
// 'subjects[]=First%20Subject&subjects[]=Second%20Subject'
Note:
For empty arrays (e,g: let arr = [];) this method responds with subjects[]=, which php reads as an array with a single empty string (e,g: print_r($_REQUEST["subjects"]) prints Array ( [0] => )).
I couldn't find a standard for sending empty arrays url encoded and you should handle that somewhere.
I'm trying to retrieve data from my service function, but am running into issues. My LandingPage component code, shown below, sends a keystroke to my service function, which then returns an object full of data.
But I cannot get the service object to return to my LandingPage. Here is how I create my service:
task.service.ts
addKey(keystroke) {
const query = "https://api.themoviedb.org/3/search/tv?api_key=";
fetch(query + key + '&language=en-US&query=' + keystroke)
.then((show) => {
show.json().then((obj) => {
// grab the items we want from the response
let resultItems = obj.results.map((show, index) => {
return {
id: show.id,
poster: show.poster_path,
rating: show.vote_average,
backdrop: show.backdrop_path,
};
});
// return our newly formed object
return { data: resultItems }
});
});
}
Here is where I am trying to receive the service data, in my:
landingpage.component.ts
getKey(keystroke) {
this.TaskService.addKey(keystroke)
.subscribe(res => {
this.shows = res.data; // trying to receive service info here
});
}
When I try to build, I receive the following error in my LandingPage component:
Property 'subscribe' does not exist on type 'void'.
I've tried using map instead of subscribe, but it returns a similar error.
How can I send the object result from my service, to my component?
It looks like you're missing a return in your service method, I've also changed to using http from our discussion in the comments:
addKey(keystroke): Observable<any> {
const query = "https://api.themoviedb.org/3/search/tv?api_key=";
return this.http.get(query + key + '&language=en-US&query=' + keystroke)
.map(show => {
show.json().then((obj) => {
// grab the items we want from the response
let resultItems = obj.results.map((show, index) => {
return {
id: show.id,
poster: show.poster_path,
rating: show.vote_average,
backdrop: show.backdrop_path,
};
});
// return our newly formed object
return { data: resultItems }
});
});
}
If you really want to use fetch you can if you:
Set the method return signature to Promise<any>
Use then instead of map in the service
Use then instead of subscribe in the component
I am trying to do a http get in angular like this:
$http
.get(some url, {
params: {
description: params.description,
from: params.from,
to: params.to
}
})
.success(function (data,status) {
$scope.info_show = data
});
here's the thing, the params object parameters are set based in user input, so if the user hasn't inputted anything for the from property (some input text fielt) it will be undefined.
my problem is that I can't just pass the params object, because it doesn't filter and if I pass undefined on even one of the properties then the web service by default will return everything, could someone show me a way of dynamically doing this?
You could use a function to filter the params object.
This one receives a list of params/properties you want to filter and the src object to filter from:
var filterParams = function(params, src) {
var result = {};
angular.forEach(params, function(p) {
if (angular.isDefined(src[p])) {
result[p] = src[p];
}
});
return result;
};
And then use it like this:
$http.get(some url, {
params: filterParams(['from', 'to', 'description'], params)
})
.success(function (data,status) {
$scope.info_show = data
});
I'm trying to figure out how to create a nested $resource. I have come up with the following, which seems to work..ish, but seems awfully wrong. Hoping someone can point me in the right direction.
My data structure is:
allData = [{
id:1,
info:'someinfo',
foo :'foobar',
bar : {...},
baz : [{...}, {...}, {...}]
},
{id:2, ...},
{id:3, ...}
];
I would like each object in allData to be a $resource object. I also want each object in the baz array to be a $resource object as well.
What I have come up with is:
var InfoService = angular.module('InfoServices', ['ngResource']);
// The inner resource
InfoService.factory('Baz', ['$resource',
function($resource) {
var baz = $resource('/server/baz', {});
// custom baz methods
baz.prototype.getBaz = function() {};
return baz;
}]);
// Outer resource
InfoService.factory('Info', ['$resource',
function($resource) {
var info = $resource('/server/info', {});
// custom data methods
info.prototype.getInfoStats = function() {};
return info;
}]);
// Array of resources.
InfoService.factory('AllInfo', ['$resource','Info', 'Baz',
function($resource,Info,Baz) {
var resource = $resource('/server/allinfo', {},
{ query : {
method:'get',
isArray:true,
transformResponse:function(data) {
var allinfo = JSON.parse(data);
for (var i=0;i<allinfo.length;i++) {
allinfo[i] = new Info(allinfo[i]);
for (var j=0;j<allinfo[i].baz.length;j++) {
allinfo[i].baz[j] = new Baz(allinfo[i].baz[j]);
}
}
return allinfo;
}
});
return resource;
}]);
Like I said..seems awfully wrong, what's the Angular way to achieving the above?
InfoService.factory('resources', function($resource) {
return {
id: $resource(...),
info: $resource(...),
//...and so on...
}
})
//example usage
InfoService.controller('ctrl', function(resources) {
this.id = resources.id.query();
})
If you want to make everything a resource, this is the way to go. But ask yourself...is it really necessary to make every attribute a separate resource? What about grouping in a resource all attributes that are strictly related? I ask because I am not sure of what these data rapresent to you.
by making request to WebAPI I expect to receive string array with several values (units of measurement in this case) ["KGM", "MTR"]
Unfortunately in response I'm receiving array of resources and within array of chars
[0] Resource
[0]: "K"
[1]: "G"
[2]: "M"
[1] Resource
[0]: "M"
[1]: "T"
[2]: "R"
img: http://snag.gy/dDerV.jpg
Here is request which I do and how I'm carry the response
var provider = this.resource(WebAPIDataUrl, {}
, {
GetData: {
method: 'GET'
, params: {
action: "GetData"
}, isArray: true
, headers: {
'Token': this.window.sessionStorage.getItem("Token")
}
}
});
var _success = function (resource: string[]) {
_unitsOfMeasurements = Object.keys(resource);
};
var _error = function () {
};
provider.GetData(_success, _error);
I have also created a hook by using transformResponse to be sure that incoming data is in proper format and it's ok:
transformResponse: function(data, headers){
return data;
}
data == '["KGM", "MTR"]'
So question is how should treat response to have nice string[] ?
Can you share the raw response with us?
If you need to work with the response you have, you can obtain the strings using the array.prototype.join method.
response = [
['K','G','M'],
['M','T','R']
];
for (var i = 0; i < response.length; i++) {
var string = response[i].join('');
console.log(string);
}
$resource only works with objects or arrays of objects, not strings.
You could wrap the strings in objects or as a suggestion in this thread regarding this issue says, if you want an array of strings you could use $http instead.