Trying to post object with parameters - angular js - javascript

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

Related

JavaScript - Url encoding of Array type parameters

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.

Retrieving object data from a service in Angular 2

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

Accessing the query variable from within callback

Take the following example:
getOptions() {
let options = {};
if (this.props.location.hasOwnProperty('query')) {
const query = this.props.location.query;
const queriesMap = {
'createdBy': 'createdBy',
'state': 'state',
'created_from': 'created_at[from]',
'created_to': 'created_at[to]'
};
Object.keys(query).map(function(key) {
if(queriesMap.hasOwnProperty(key)) {
options = Object.assign(options, { queriesMap[key]: query[key] });
}
});
}
return options;
}
I'm using the queriesMap object to map url parameters to build a new url to call an API. The problem is that query is undefined when I'm trying to access it from within the .map callback.
How do I access the query variable?
Looks like you are missing a [] around queriesMap[key]. So it should be options = Object.assign(options, { [queriesMap[key]]: query[key] });.
Also, you could just do options[queriesMap[key]] = query[key] rather than Object.assign

Angularjs : fitlering json properties to be send in a request

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']))

Backbone.Model save -- returned model's child is array not Backbone.Collection.

I have a Model that looks like:
var Playlist = Backbone.Model.extend({
defaults: function() {
return {
id: null,
items: new PlaylistItems()
};
}
});
where PlaylistItems is a Backbone.Collection.
After I create a Playlist object, I call save.
playlist.save({}, {
success: function(model, response, options) {
console.log("model:", model, response, options);
},
error: function (error) {
console.error(error);
}
});
In here, my model is a Backbone.Model object. However, its child, items, is of type Array and not Backbone.Collection.
This was unexpected behavior. Am I missing something? Or, do I need to manually pass my array into a new Backbone.Collection and initialize this myself?
It kind of depends on what your server is expecting and what it responds with. Backbone does not know that the attribute items is a Backbone Collection and what to do with it. Something like this might work, depending on your server.
var Playlist = Backbone.Model.extend({
defaults: function() {
return {
id: null,
items: new PlaylistItems()
};
},
toJSON: function(){
// return the json your server is expecting.
var json = Backbone.Model.prototype.toJSON.call(this);
json.items = this.get('items').toJSON();
return json;
},
parse: function(data){
// data comes from your server response
// so here you need to call something like:
this.get('items').reset(data.items);
// then remove items from data:
delete data.items;
return data;
}
});

Categories