API Call is going after providing conditions in JavaScript - javascript

I am trying to make API call and sending storeId and consultuntId to backend, its working fine.
This is the code:-
const urlParams = new URL(window.location.href).searchParams;
const live_shopping_events_parameter = Object.fromEntries(urlParams);
$.ajax({
type:'POST',
url: '/aos/lscommission',
data: {
storeId: live_shopping_events_parameter.r,
consultuntId: live_shopping_events_parameter.z,
},
success: function (){
},
error: function(error) {
},
});
But I need to check two condition
the url fields exist and are valid
non-empty numeric for storeId and consultantId
This is the Example URL - https://www.example.com/live-shopping-events?r=MDQyMDE%3d&z=56
Where r is is the storeId and z is the consultuntId.
This is my code to check non-empty numeric for storeId and consultantId
const urlParams = new URL(window.location.href).searchParams;
const live_shopping_events_parameter = Object.fromEntries(urlParams);
if(live_shopping_events_parameter !== 'undefined' || live_shopping_events_parameter !== null ) {
$.ajax({
type:'POST',
url: '/aos/lscommission',
data: {
storeId: live_shopping_events_parameter.r,
consultuntId: live_shopping_events_parameter.z,
},
success: function (){
},
error: function(error) {
},
});
}else{
console.log("error");
}
for this code if I remove parameters (https://www.example.com/live-shopping-events), then still it is making API call.
How to solve this issue.

You are trying to condition in the whole object returning from Object.entries which will always return an object. That is why your condition is becoming true always. You should try to factor in the property you are trying to find, like this:
if (live_shopping_events_parameter.r !== undefined || live_shopping_events_parameter.z !== undefined) {
/* You code here */
}

SOULTION EXPLAINATION:
Thats because irrespective if there are url params or not the Object.fromEntries(urlParams) will return an object. If you want to check if params exist you need to check individually like live_shopping_events_parameter.r, this will return true is param exists and false if param is absent and make API call only when it is true.
SOULTION CODE:
const urlParams = new URL(window.location.href).searchParams;
const live_shopping_events_parameter = Object.fromEntries(urlParams);
if(live_shopping_events_parameter.r && live_shopping_events_parameter.z) {
//Params exist
//Make API call here..
console.log('Calling API')
}else{
// No params found
console.log('Params missing')
}

Related

How to check if an id is already present in a firebase realtime database using react.js

I am working on an inventory project using React. Before pushing the data in progress.json I want to check if that data is already present in progress.json file to prevent duplication using the id provided to each dataset. As I am still learning React I am out of solutions for this problem.
export async function progressOrders (found){
const loadedOrders = await fetchOrders('progress');
let result;
//for(const key in loadedOrders){
// result = loadedOrders.filter(() => {
// return loadedOrders[key].id === found.id
// });
//};
loadedOrders.map(() => {
for(const key in loadedOrders){
if(loadedOrders[key].id === found.id){
return result = true;
}else{
return result = false;
}
}
return result;
});
console.log(result);
if(result === true){
alert('Order already in progress state');
}else{
const response = await fetch(`${FIREBASE_DOMAIN}/progressOrders.json`,{
method:"POST",
headers:{
"Content-Type": "application/json"
},
body: JSON.stringify({
id: found.id,
dryFruit: found.dryFruit,
weight: found.weight,
canteenName: found.canteenName,
orderQuantity: found.orderQuantity,
newOrderTime: found.newOrderTime
})
});
if(!response){
throw Error('Order not in progress');
}else{
alert('Order is in progress now.');
};
}
};
If you want to prevent duplication, always use the thing that needs to be unique as the key for that data in the database.
Where you now store:
progressOrders: {
"somemeaninglesspushid": {
...
"id": "orderIdThatMustBeUnique"
}
}
Consider changing that to:
progressOrders: {
"orderIdThatMustBeUnique": {
...
}
}
With this data structure the order ID is by definition going to be unique inside of progressOrders, as keys are by definition unique with a JSON object.
This new data structure also ensures that there's no harm in writing the same order information multiple times. The result after the second (or any subsequent) write is the same as the result after the first write, a concept known as idempotency.

async js validation form

Good morning !
Currently I am trying to create some kind of simple validation using javascript, but I have a problem with using async functionalities.
Below you can see UI method which iterates through validityChecks collections
checkValidity: function(input){
for(let i = 0; i<this.validityChecks.length; i++){
var isInvalid = this.validityChecks[i].isInvalid(input);//promise is returned
if(isInvalid){
this.addInvalidity(this.validityChecks[i].invalidityMessage);
}
var requirementElement = this.validityChecks[i].element;
if(requirementElement){
if(isInvalid){
requirementElement.classList.add('invalid');
requirementElement.classList.remove('valid');
}else{
requirementElement.classList.remove('invalid');
requirementElement.classList.add('valid');
}
}
}
}
Below is specific collection object which is not working as it was intended
var usernameValidityChecks = [
{
isInvalid: function(input){
var unwantedSigns = input.value.match(/[^a-zA-Z0-9]/g);
return unwantedSigns ? true:false;
},
invalidityMessage:'Only letters and numbers are allowed',
element: document.querySelector('.username-registration li:nth-child(2)')
},
{
isInvalid: async function (input){
return await checkUsername(input.value);
},
invalidityMessage: 'This value needs to be unique',
element: document.querySelector('.username-registration li:nth-child(3)')
}
]
function checkUsername (username) {
return new Promise ((resolve, reject) =>{
$.ajax({
url: "check.php",
type: "POST",
data: { user_name: username },
success: (data, statusText, jqXHR) => {
resolve(data);
},
error: (jqXHR, textStatus, errorThrown) => {
reject(errorThrown);
}
});
});
}
The problem is that to var isInvalid in checkValidity method is returned promise. Can anyone advice how to returned there value instead of promise ? Or how to handle promise there ?
Thank you in advance!
EDIT :
Forgive me, but it is my first time with Stack and probably my question is a little bit inaccurate. Some of objects in collections are also synchronous, I changed usernameValidityChecks. How to handle this kind of situation ? Where I have async and sync method at the same time ?
Instead of below line
var isInvalid = this.validityChecks[i].isInvalid(input);
you can use below code to make code much cleaner and store the desired value on the variable however above suggested solutions are also correct
var isInvalid = await this.validityChecks[i].isInvalid(input).catch((err) => { console.log(err) });
After this line you will get the desired value on isInvalid variable
And also add async keyword in all other isInvalid function definition
Use .then to access the result of a promise:
var isInvalid = this.validityChecks[i].isInvalid(input).then(res => res);

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)

Manipulate ajax response

I have a ajax post method. I get an object from the backend
$.ajax({
type: "POST",
url: URL_one,
data: submitData
}).then(function (response) {
console.log("Ajax response", response);
});
and when i do a console.log(response); inside the post method, i see the following data.
>Object{Info:Array[200]}
>Info:Array[200]
>[0-99]
>0:Object
name:'Ashley'
on_pay: true
valid:"0"
>[100-199]
So each array has objects like one mentioned above with name, on_pay and valid. I want to do the following
Since all on_pay values are true in my case, i need to convert it to false. Also valid has string of 0. I need to put all values as blank instead of 0.
Is it possible to do ?? Can someone please shed some light on these.
Considering the JSON structure that you show, following should work to change the on_pay value:
response.Info.forEach(function(item){
item.on_pay = false;
});
If I'm understanding your question correctly, response is an array of items. You want to keep those items intact, but turn the on_pay property false and valid to an empty string.
You can use Array::map() to transform each item.
/*jslint node:true*/
"use strict";
// I am assuming your response looks something like this
var response = {
Info: [
{
name: "Ashley",
on_pay: true,
valid: "0"
},
{
name: "Jim",
on_pay: true,
valid: "0"
},
{
name: "John",
on_pay: true,
valid: "0"
}
]
};
// This will produce a new variable that will hold the transformed Info array
var fixedResponseInfo = response.Info.map(function (item) {
item.on_pay = false;
item.valid = "";
return item;
});
// This will edit the response.Info array in place
response.Info.forEach(function (item) {
item.on_pay = false;
item.valid = "";
});
console.log(fixedResponseInfo);
console.log(response);
This will keep your original response variable and produce a new variable fixedResponseInfo that contains the transformed array. If you don't care whether data in response is changed, you can use Array::forEach() to iterate instead.

Access Backbone fetch parameters

I need to be able to pass the server some info when calling fetch on a Backbone collection. On my front-end I have this code, passing data:{} to the fetch function along with the success and error callbacks. Looking at the docs for Backbone fetch:
http://backbonejs.org/#Collection-fetch
perhaps I am not passing in the parameters correctly to the fetch function? Perhaps they should be in an array []...
var lineupCollection = new LineupCollection([]);
var loadTeamsOnPageLoad = (function() {
lineupCollection.url = '/api/lineups';
lineupCollection.fetch(
{
processData: true,
data: {
team_id:$("#team_id").attr("value")
}
},
{
success: function (result) {
if(window.teamDashboardTableView === undefined){
window.teamDashboardTableView = new TeamDashboardTableView({el: $("#team-dashboard-table-div")});
}
window.teamDashboardTableView.render();
},
error: function (err) {
setTimeout(function () {
alert('error fetching lineupCollection - ' + err.message);
}, 1);
}
}
);
})();
which will load a Backbone collection into a table.
It's call this method on the back-end:
exports.getBackboneLineups = function(req,res,next){
var user_id = req.mainUser._id;
console.log('req.params',req.params); //empty {}
console.log('req.team',req.team); //undefined
console.log('team_id',req.team_id); //undefined
console.log('req.data',req.data); //undefined
console.log('req.body',req.body); //empty {}
var team_id = req.team._id; //undefined EXCEPTION, can't read property _id of undefined
var system_db = req.system_db;
var Lineup = LineupModel.getNewLineup(system_db,user_id);
Lineup.find({team_id:team_id}, function (err, lineups) {
if (err) {
return next(err);
}
res.json(lineups);
});
};
however, I am totally failing as far as how to access the data that I supposedly past to the server from the client. I can't really find a good example and I am getting tired of guessing. What's the best way to do this?
edit:
also tried passing {data:{}, success: function(), error: function()} all in the same JavaScript object, but that didn't work.
fetch only takes one argument (see http://backbonejs.org/#Collection-fetch). Instead, you should probably alter your backend to specify the team id in the resource's URL. For example:
lineupCollection.url = function(){ return '/api/lineups?team_id=' + this.team_id; };
lineupCollection.team_id = $("#team_id").attr("value");
lineupCollection.fetch({ success: ..., error: ...});

Categories

Resources