How to propertly pass query string parameters? Angular - javascript

I want to send an HTTP request with parameters via a query
Example:
URL: https://api/endpoint?d=1&value=2

To add params for your URL, you need to create the correct options, for example:
const options = { params: new HttpParams().set('value1', '1').set('value2', '2') };
return this.http.get(`${APP_BASE_URL}/endpoint`, options);
Before is an example, you can create a petition with params of many ways.
Check the documentation here

You can create an object and pass it as 2nd parameter in get method.
const url="example.com/data";
const parameters = {
'value1': 1,
'value2': 2
};
return this.httpClient.get(url, {
params: parameters
})
This will create your url like below:-
URL: https://api/endpoint?value1=1&value2=2

Related

Handling Optional Query Params in NodeJS API [duplicate]

I want to send in response some data according to searching by query parameters (using .find function of mongoose) from the client side. What do I need to do is a search according to the parameters received?
What I mean is :
I may receive
localhost:5000/admin/customers?customer_id=1&customer_email=abc#gmail.com
I could have used this code to send results according to this query :
Customer.find({
customer_id = req.query.customer_id,
customer_email = req.query.customer_email,
}, (err,docs)=> {
res.json(docs);
})
or
just
localhost:5000/admin/customers?customer_id=1
I could have used this code to send results according to this query :
Customer.find({
customer_id = req.query.customer_id
}, (err,docs)=> {
res.json(docs);
})
or
may be
localhost:5000/admin/customers?no_of_items_purchased=15
I could have used this code to send results according to this query :
Customer.find({
no_of_items_purchased = req.query.no_of_items_purchased
}, (err,docs)=> {
res.json(docs);
})
But what I want is to use .find function on anything received from query params. Like a general code to achieve this.
PS: Also please help with : "How to filter req.query so it only contains fields that are defined in your schema ?"
You can create a query variable to keep the field that you want to filter.
Suppose that your Customer model structure is:
{
customer_id: ...,
customer_name: ...,
customer_email: ...,
no_of_items_purchased: ...
}
Then your code will be:
let {customer_id, customer_name, customer_email, no_of_items_purchased} = req.query;
let query = {};
if (customer_id != null) query.customer_id = customer_id;
if (customer_name != null) query.customer_name = customer_name;
if (customer_email != null) query.customer_email = customer_email;
if (no_of_items_purchased != null) query.no_of_items_purchased = no_of_items_purchased;
let result = await Customer.find(query);
Just pass request.query as a parameter directly on find method:
Customer.find(request.query)

Axios - How not to add [] to the multi parameters?

Axios adds square brackets to the param if there are multiple params with an equal name. The problem is that I need not to include those brackets since I use Django Rest Framework and Django Filters.
How can I do that if I use this notation?
axios.get(list_url, {params: {somelist:[1,2,3]}})
I don't want url/?somelist[]=1&somelist[]=2&somelist[]=3
Instead I want url/?somelist=1&somelist=2&somelist=3
Try to do it using paramsSerializer's indexes:null in axios config
axios.get(someurl, {
params: {
foo: [1, 2, 3]
},
paramsSerializer: {
indexes: null
}
});
I got this from here https://www.npmjs.com/package/axios#axios-api
screenshot with attributes of paramsSerializer
You can do like this with URLSearchParams (a native object that exists in browsers and in Node.js as well):
const axios = require('axios');
const { URLSearchParams } = require('url');
var params = new URLSearchParams();
params.append("q", 'test');
params.append("foo", 2);
params.append("foo", 11);
var request = {
params: params
};
axios.get('http://google.com/', request).then(x => x.request).then(console.log);

How to correctly use axios params with arrays

How to add indexes to array in query string?
I tried send data like this:
axios.get('/myController/myAction', { params: { storeIds: [1,2,3] })
And I got this url:
http://localhost/api/myController/myAction?storeIds[]=1&storeIds[]=2&storeIds[]=3
So, I should to get this url:
http://localhost/api/myController/myAction?storeIds[0]=1&storeIds[1]=2&storeIds[2]=3
What I should add in my params options to get this url?
You can use paramsSerializer and serialize parameters with https://www.npmjs.com/package/qs
axios.get('/myController/myAction', {
params: {
storeIds: [1,2,3]
},
paramsSerializer: params => {
return qs.stringify(params)
}
})
Without having to add more libraries and using ES6 you could write:
axios.get(`/myController/myAction?${[1,2,3].map((n, index) => `storeIds[${index}]=${n}`).join('&')}`);
Thanks so much the answer from Nicu Criste, for my case, the API requires params like this:
params: {
f: {
key: 'abc',
categories: ['a','b','c']
},
per_page: 10
}
Method is GET and this API requires the format is: API?f[key]=abc&f[categories][]=a&f[categories][]=b...
So I assigned the paramsSerializer of axios like this:
config.paramsSerializer = p => {
return qs.stringify(p, {arrayFormat: 'brackets'})
}
Install qs please go to this link
Read more about paramsSerializer in axios document
Edit format of params: Read more at qs stringifying document
In my case, I use ES6 array function.
array element make querystring use reduce function.
Object array also works.
const storeIds = [1,2,3]
axios.get('some url', {
params: {
storeIds: storeIds.reduce((f, s) => `${f},${s}`)
}
})
In my case, I am using someting like this
const params = array.map((v)=>{
return `p=${v}&`
})
Only concat params.join('') to the URL where you get data:
`url_to_get?${params.join('')`
In my back-end in ASP.net I receive this
[FromUri] string [] p
This answer is inspired by #Nicu Criste's answer.
But might be not related to the posted question.
The following code was used to generate the query params with repetitive keys which had been supplied with an object array.
Note: If you are a developer with bundlephobia, use the following approach with care: as with UrlSearchParams support varies on different browsers and platforms.
const queryParams = [{key1: "value1"}, {key2: "value2"}]
axios.get('/myController/myAction', {
params: queryParams,
paramsSerializer: params => {
return params.map((keyValuePair) => new URLSearchParams(keyValuePair)).join("&")
}
})
// request -> /myController/myAction?key1=value1&key2=value2
I rewrote the existing paramSerializer shipped in axios. The following snippet does the same serialization while putting indices between square brackets. I tried qs but it is not compatible with my python connexion backend (for JSON string parameters).
const rcg = axios.create({
baseURL: `${url}/api`,
paramsSerializer: params => {
const parts = [];
const encode = val => {
return encodeURIComponent(val).replace(/%3A/gi, ':')
.replace(/%24/g, '$')
.replace(/%2C/gi, ',')
.replace(/%20/g, '+')
.replace(/%5B/gi, '[')
.replace(/%5D/gi, ']');
}
const convertPart = (key, val) => {
if (val instanceof Date)
val = val.toISOString()
else if (val instanceof Object)
val = JSON.stringify(val)
parts.push(encode(key) + '=' + encode(val));
}
Object.entries(params).forEach(([key, val]) => {
if (val === null || typeof val === 'undefined')
return
if (Array.isArray(val))
val.forEach((v, i) => convertPart(`${key}[${i}]`, v))
else
convertPart(key, val)
})
return parts.join('&')
}
});
I got using "paramSerializer" a bit confuse. Before looking for the "right way" to use axios with array querystring on Google, I did following and got working:
var options = {};
var params = {};
for(var x=0;x<Products.length;x++){
params[`VariableName[${x}]`] = Products[x].Id;
}
options.params = params;
axios.get(`https://someUrl/`, options)...
It is going to create querystring parameters like:
VariableName[0]=XPTO,VariableName[1]=XPTO2
which the most webservers expected as array format
I know that this approach is not very good and I don't know the downsides it may have, but i tried this and it worked:
before making the request, prepare the params:
let params = '?';
for (let i = 0; i < YOUR_ARRAY.length; i++) { // In this case YOUR_ARRAY == [1, 2, 3]
params += `storeIds=${YOUR_ARRAY[i]}`; // storeIds is your PARAM_NAME
if (i !== YOUR_ARRAY.length - 1) params += '&';
}
And then make the request like so:
axios.get('/myController/myAction' + params)
In React I needed to use axios with a params in array. This was query param:
"fields[0]=username&fields[1]=id&populate[photo][fields][0]=url&populate[job][fields][1]=Job"
to send with axios, for that I installed by CLI
npm install qs Read more about qs
and declared
const qs = require('qs');
after
const query = qs.stringify({
fields: ['username', 'id'],
populate: {
photo: {
fields: ['url']
},
job: {
fields: ['Job']
}
}
}, {
encodeValuesOnly: true
});
and finally I called the axios like this:
axios.create({
baseURL: "http://localhost:1337/api/",
}).get(`/users?${query}`) // this parameter show all data
.then((response) => console.log(response.data))
.catch((err) => {
setError(err);
});
Basically, reading from docs https://axios-http.com/docs/req_config
paramsSerializer is an optional function, which we should use if the default serialization of params done by axios is not as expected. We can use serialization libraries (which I feel is best approach) to serialize in the params in the paramsSerializer function as per our needs.
Let's see an example.Suppose params is like ...
{
params: {
delay: 1,
ar:[1,2,3]
}
}
then you will get queryString like this ?delay=1&ar[]=1&ar[]=2&ar[]=3 when you make the request, but you might want like this
?delay=1&ar[0]=1&ar[1]=2&ar[2]=3 so in order to get query string as per our format. we can use qs https://www.npmjs.com/search?q=qs library and serialize our params in the paramsSerializer function as below
{
method: "GET",
params: {
delay: 1,
ar:[1,2,3]
},
paramsSerializer: (params) => {
return qs.stringify(params,{
encodeValuesOnly: true
});
}
},
This work it for me:
axios.get("/financeiro/listar",{
params: {
periodo: this.filtro.periodo + "",
mostrarApagados: this.filtro.mostrarApagados,
mostrarPagos: this.filtro.mostrarPagos,
categoria: this.filtro.categoria,
conta: this.filtro.conta
}
})
This was better for me:
axios.get('/myController/myAction', {
params: { storeIds: [1,2,3] + ''}
})
In my case, there was already jQuery implemented into my codebase. So I just used the predefined method.
jQuery.param(Object)

How can I get HttpParams values as JSON object?

I'm using Angular 5 with HttpInterceptors.
I already know I can get each value I want from HttpParams via several methods.
Also - If I want to see all values , I can use the .toString() method
params = new HttpParams()
.set('page', '2')
.set('sort', 'name');
console.log(params.toString()); //Returns page=2&sort=name
But in my case I send json objects as parameters :
{
a:1 , b:[1,2,3] , c:[{...}]
}
I'm using interceptors to log the request parameters , but when I JSON.stringify(req.Params) , I get :
Params={
"updates": null,
"cloneFrom": null,
"encoder": {},
"map": {}
}
Which doesn't expose the values.
I don't want to see the parameters as a regular form post parameters -( it will be very unclear), but as an object as I've sent it.
Question:
How can I extract the parameters from the request object in the interceptor , but as json format :
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>
{
JSON.stringify( req.params) // <--- ?? doesn't yield the params.
}
If you don't like method toString() that returns an encoded string, where key-value pairs (separated by =) are separated by &s you can write your own method that will transform data stored in Map in some data you want to use.
For example:
const params = new HttpParams()
.set('page', '2')
.set('sort', 'name');
const paramsArray = params.keys().map(x => ({ [x]: params.get(x) }));
console.log(JSON.stringify(paramsArray));
It's similar to the approach that is used in toString method
https://github.com/angular/angular/blob/master/packages/common/http/src/params.ts#L177-L186
Ng-run Example
What you actually requested was a JSON Object. So this is how you get such an object:
const params = new HttpParams()
.set('page', '2')
.set('sort', 'name');
const paramsObject = params.keys().reduce((object, key) => {
object[key] = params.get(key)
return object
}, {})
console.log(paramsObject)
// And json if you really want
const json = JSON.stringify(paramsObject)

ASP.NET MVC controller accept javascript object

From chrome developer tools I see that my request is sending this info to my controller:
models:[{"Id":null,"Start":"2014-06-11T12:17:52.452Z","End":"2014-06-11T12:17:52.452Z","Name":"test","Status":"test"}]
How can I accept it in my MVC controller?
It looks like to be a javascript array with one element.
On serverside I have method accepting : Foo(Bar models) and also tried Foo(List<Bar> models)
The models value is always null. Any suggestions, how to get the value to my server?
So to pass the information using AJAX, you need to supply two parameters: dataType and contentType. (I suppose dataType is optional, but if you're expecting JSON back it's better to supply it.). The contentType, however, lets MVC [the ModelBinder] know the incoming request isn't just a string, but that it's an object that needs to be deserialized back into objects.
with that said, something like the following should work for your circumstance:
// This is your to-be-sent data'
// However you collect it, but for now we're storing it as a plain object.
var jso = { models: [{ "Id": null, "Start": "2014-06-11T12:17:52.452Z", "End": "2014-06-11T12:17:52.452Z", "Name": "test", "Status": "test" }] }
// Here we turn it into JSON
var json = JSON.stringify(jso);
// And now we send it off to the controller/action:
$.ajax({
url: '#Url.Action("SomeAction","SomeController")',
type: 'POST',
data: json, // pass of data serialized
dataType: 'json', // expecting json back
contentType: 'application/json; charset=utf-8', // hey ModelBinder, deserialize this!
})/* handle the Deferred callbacks (.done, .fail, .always) */;
Then, in your controller:
public class SomeController : Controller
{
[HttpPost]
public JsonResult SomeAction(IList<MyModel> models)
{
// Should pass now
if (ModelState.IsValid)
{
// Handle it and return back the response
// Given the above, you have something like the following now
// assigned to "models":
// models = new List<MyModel> {
// new MyModel {
// Id = null,
// Start = new DateTime(2014, 11, 6, 12, 17, 52),
// End = new DateTime(2014, 11, 6, 12, 17, 52),
// Name = "test",
// Status = "test"
// }
// };
return Json(new {Models = models }); // just to see it come back
}
return Json(new { Error = true, Message = "Invalid model" });
}
}
Working example can be seen On GitHub by the way.
Here is a pretty simple example using POST and Json.Net to deserialize into a JObject
Get Json.Net via Nuget.
API Controller:
[HttpPost]
public dynamic UpdateItem([FromBody]dynamic item)
{
var qp = JObject.Parse(item.ToString());
string oid = qp.SelectToken("oid").ToString();
...
Make sure your route and param name matches an actual route, for example
config.Routes.MapHttpRoute(
name: "ItemApi",
routeTemplate: "api/{controller}/{action}/{item}",
defaults: new { item = RouteParameter.Optional }
);
Usually found under App_Start/WebApiConfig.cs or in global.asax.
And then post to it using jquery ajax:
var param = new Object();
param.oid = "somestring";
param.name = "john";
param.number = 3;
$.ajax({
type: "POST",
url: "/api/YourController/UpdateItem",
data: JSON.stringify(param),
contentType: 'application/json',
success: function (data) {
// do stuff
},
error: function (e) {
console.error("error", e);
}
});
EDIT: I see now that you are using a mvc controller. I assumed a webapi controller for my answer. Apologizes :)
It is mvc's default behaviour it will convert json object to your C# object automatically. just makesure property name matches. Check this may help
For that you need to use JsonConvert.DeserializeObject() method.
Like this
List<YourModelClass> myObjList =
(List<YourModelClass>)Newtonsoft.Json.JsonConvert.DeserializeObject(models, typeof(List<test>));
Then return this object named - myObjList to your view or whatever...
And For single object -
return JsonConvert.DeserializeObject<YourModelClass>(models);

Categories

Resources