How to pass value into array in node - javascript

Hi Im still learning node and trying something cool with javascript nodejs.
Meanwhile I got stuck when pass separate "where" sequelize statement into one.
Okay, this is my current code :
var periodsParam = {};
periodsParam = {
delete: 'F',
tipe: 1,
variantid: (!ctx.params.id ? ctx.params.id : variants.id)
};
if (ctx.query.country) {
periodsParam = {
country: ctx.query.country
};
}
console.log(periodsParam);
From code above, its always return { country: 'SG' } , but I want to return { delete: 'F', tipe: 1, variantid: 1, country: 'SG' }
How can I resolve that ?
Anyhelp will appreciate, thankyouu.

The problem is, you're using = sign with periodsParam 3 times and you end up with periodsParam returning only country, because of this lines:
if (ctx.query.country) {
periodsParam = {
country: ctx.query.country
};
}
Instead of assigning new object to periodsParam, use dot notation to add another key-value pair, like this:
if (ctx.query && ctx.query.country) { //before accesing .country check if ctx.query is truthy
periodsParam.country = ctx.query.country;
}
As #Paul suggested, condition should be ctx.query && ctx.query.country - it will prevent TypeError if ctx.query is undefined.

The problem was that you were always re initializing it. You should set it as a property of the existing object.
Update from
periodsParam = {
country: ctx.query.country
};
to
periodsParam.country = ctx.query.country;

You can also just assign the Object like this:
periodsParam = Object.assign({}, periodsParam, { country: ctx.query.country });

Related

javascript string comparison issue in array.filter()

I have an array which contains following objects.
myArray = [
{ item: { id: 111557 } },
{ item2: { id: 500600 } }]
and I have a variable
targetItemID = '111557'
Note that one is string, and the ones in array are numbers. I'm trying to get the object having the correct item id.
Here is what I have tried,
myArray = [
{ item: { id: 111557 } },
{ item2: { id: 500600 } }]
targetItemID = '111557'
var newArray = myArray.filter(x => {
console.log(x.item.id.toString())
console.log(targetItemID.toString())
x.item.id.toString() === itemID.toString()
})
console.log(newArray);
I expect all matching objects to be added to 'newArray'. I tried to check the values before comparison, They are both strings, they seem exactly same, but my newArray is still empty.
Your second object doesn't have an item property and should.
You need a return in your filter function.
You must compare x.item.id against targetItemID, not itemID. Since you are using console.log() you would have seen and error of itemID id not defined ;).
myArray = [
{ item: { id: 111557 } },
{ item: { id: 500600 } }
];
targetItemID = '111557'
var newArray = myArray.filter(x => {
//console.log(x.item.id.toString())
//console.log(targetItemID.toString())
return x.item.id.toString() === targetItemID.toString();
});
console.log(newArray);
There are a few issues here. First, not all your objects have an item property, so you'll need to check it exists. Second, you're comparing them against a non-existent itemID instead of targetItemID, and finally, and #bryan60 mentioned, if you open a block in an anonymous lambda, you need an explicit return statement, although, to be honest, you really don't need the block in this case:
var newArray =
myArray.filter(x => x.item && x.item.id && x.item.id.toString() === targetItemID)
you need to return for filter to work:
return x.item.id.toString() === itemID.toString();

Vue computed property changes the data object

I have basically this structure for my data (this.terms):
{
name: 'First Category',
posts: [
{
name: 'Jim James',
tags: [
'nice', 'friendly'
]
},
{
name: 'Bob Ross',
tags: [
'nice', 'talkative'
]
}
]
},
{
name: 'Second Category',
posts: [
{
name: 'Snake Pliskin',
tags: [
'mean', 'hungry'
]
},
{
name: 'Hugo Weaving',
tags: [
'mean', 'angry'
]
}
]
}
I then output computed results so people can filter this.terms by tags.
computed: {
filteredTerms: function() {
let self = this;
let terms = this.terms; // copy original data to new var
if(this.search.tags) {
return terms.filter((term) => {
let updated_term = {}; // copy term to new empty object: This doesn't actually help or fix the problem, but I left it here to show what I've tried.
updated_term = term;
let updated_posts = term.posts.filter((post) => {
if (post.tags.includes(self.search.tags)) {
return post;
}
});
if (updated_posts.length) {
updated_term.posts = updated_posts; // now this.terms is changed even though I'm filtering a copy of it
return updated_term;
}
});
} else {
return this.terms; // should return the original, unmanipulated data
}
}
},
filteredTerms() returns categories with only the matching posts inside it. So a search for "angry" returns just "Second Category" with just "Hugo Weaving" listed.
The problem is, running the computed function changes Second Category in this.terms instead of just in the copy of it (terms) in that function. It no longer contains Snake Pliskin. I've narrowed it down to updated_term.posts = updated_posts. That line seems to also change this.terms. The only thing that I can do is reset the entire data object and start over. This is less than ideal, because it would be loading stuff all the time. I need this.terms to load initially, and remain untouched so I can revert to it after someone clears their search criterea.
I've tried using lodash versions of filter and includes (though I didn't really expect that to make a difference). I've tried using a more complicated way with for loops and .push() instead of filters.
What am I missing? Thanks for taking the time to look at this.
Try to clone the object not to reference it, you should do something like :
let terms = [];
Object.assign(terms,this.terms);
let terms = this.terms;
This does not copy an array, it just holds a reference to this.terms. The reason is because JS objects and arrays are reference types. This is a helpful video: https://www.youtube.com/watch?v=9ooYYRLdg_g
Anyways, copy the array using this.terms.slice(). If it's an object, you can use {...this.terms}.
I updated my compute function with this:
let terms = [];
for (let i = 0; i < this.terms.length; i++) {
const term = this.copyObj(this.terms[i]);
terms.push(term);
}
and made a method (this.copyObj()) so I can use it elsewhere. It looks like this:
copyObj: function (src) {
return Object.assign({}, src);
}

Add elements to a list that belongs to a state using react

I have this json variable on my state:
this.state = {
type:
{
name: '',
type2: {
atribute: '',
parameter: [
{
value: '',
classtype: ''
}
],
name: '',
atribute1: '',
atribute2: ''
}
}
}
what I wanted to do is to add elements to my parameter list,which is empty on the beggining.
What I did was this:
addParams = () => {
let newParam = {
value: this.state.type.type2.parameter.value,
classtype: this.state.type.type2.parameter.classtype
};
/** */
this.setState(prevState => ({
type: {
// keep all the other key-value pairs of type
...prevState.type,
type2: {
...prevState.type.type2,
//this is supposed to add an element to a list
parameter: [...prevState.type.type2.parameter, newParam]
}
}
}))
}
But when executing the last line of code the following error appeared:
Uncaught TypeError: Invalid attempt to spread non-iterable instance
when spreading a list
I do not know why this does not work because the parameter is a list indeed.
If this.state.type.type2.parameter is an array then why are you referencing properties on it:
let newParam = {
value: this.state.type.type2.parameter.value,
classtype: this.state.type.type2.parameter.classtype
};
I don't think your state is structured how you expect, seems like you're replacing that array with an object at some point in your code. I suggest react-devtools to help you keep track of your state as it changes.
This isn't exactly an answer but I highly suggest using immerjs for doing these pure nested updates. I almost never recommend adding a third party library as a solution but immer is lightweight and life changing. It exports a single function called produce and uses a concept called a Proxy to perform pure updates that are written as mutations.
With immer (and your bug fixed) your code becomes this:
const newParam = {
value: this.state.type.type2.parameter.value,
classtype: this.state.type.type2.parameter.classtype
};
this.setState(produce(draftState => {
draftState.type.type2.parameter.push(newParam);
}))
It lets you write more terse code that is a lot easier to read. And yes I know that looks like a mutation, but it isn't one this is 100% pure.
Try this :
this.setState(prevState => {
return {
...prevState,
type: {
...prevState.type,
type2: {
...prevState.type.type2,
parameter: [...prevState.type.type2.parameter, newParam]
}
}
}
)

Object.assign and ... spread operator fail silent, don't add elements

I have problems with Object.assign and ... spread operator. I need to process values (object with name and value tha are objects).
Example my values object:
{
id: "12",
name: "Hotel MESSI",
email: "myemail#aol.com",
phone: "+001060666661",
otherfields: "{
country: 'ZW',
city: 'Zurick'
}"
}
otherfields comes from graphql , so it's string, i must convert to object.
With my process I look for this result:
{
id: "12",
name: "Hotel MESSI",
email: "myemail#aol.com",
phone: "+001060666661",
country: 'ZW',
city: 'Zurick'
}
The code have more code that I paste here, there is a lot of controls for values and conversion but mainly, the idea is reassing values,
With these two case assign to the same variable is not working:
Case 1, with object.assign
processValues = (values)=>
let newValues = {...values}; //
for (const fieldName in Tables[table].fields) {
let value = values[fieldName];
value = JSON.parse(value);
newValues = { ...newValues, ...value};
console.error('after mix',newValues);
Case 2, with object.assign
processValues = (values)=>
let newValues = Object.assign({}, values}; //
for (const fieldName in Tables[table].fields) {
let value = values[fieldName];
value = JSON.parse(value);
newValues = Object.assign( newValues, value};
console.error('after mix',newValues);
How it's works, when I use a new variable, by example:
newValues2 = Object.assign( newValues, value};
but my idea is not use another variable because , i need to get values and set values for the original variable 'newValues' , if I use another variable the code would be more cumbersome.
I'm using in a project with create-react-app. I don't know if it's a problem with babel, because Object.assign and spread operator are not inmmutable; or yes ?
INFO:
Tables[table].fields is a object with definition por my table structure, there therea lot of rules, but basically i need to know why object and ... does not work
The use of JSON.stringify will not help, as this will produce a JSON string, which will have an entirely different behaviour when spreading it (you get the individual characters of that string).
Here is how you can achieve the result with "otherfields" as the special field (you can add other fields in the array I have used):
const processValues = values =>
Object.assign({}, ...Object.entries(values).map( ([key, val]) =>
["otherfields"].includes(key) ? val : { [key]: val }
));
// Example:
const values = {
id: "12",
name: "Hotel MESSI",
email: "myemail#aol.com",
phone: "+001060666661",
otherfields: {
country: 'ZW',
city: 'Zurick'
}
};
const result = processValues(values);
console.log(result);
The first argument to assign is the target. So it's going to get changed. You can simply pass an empty object for your target if you don't want any of the sources to change.
When you are using first argument as {} then no value will change.
For more please refer it.
https://wecodetheweb.com/2016/02/12/immutable-javascript-using-es6-and-beyond/

Check if property is not undefined

I'm building a node+express app and I'm filling an object with JSON that's submitted from a form in the frontend. This works, unless I leave a field empty in the form so that e.g. req.body.address.street is empty/undefined.
This will result in the error:
TypeError: Cannot read property 'street' of undefined
var b = new Business({
name: req.body.name,
phone: req.body.phone,
address: {
street: req.body.address.street,
postalCode: req.body.address.postalCode,
city: req.body.address.city
},
owner: {
email: req.body.owner.email,
password: req.body.owner.password
}
});
My question is how I can best prevent my app from crashing when values are empty. I would like to avoid manually checking each and every property in my app against undefined.
I'm wondering what the best practice is for this common issue.
I don't know if you use jQuery in your project, but if you do, you can create a mask:
// creating your object mask
var req = {
body: {
name: '',
phone: '',
address: {
street: '',
postalCode: '',
city: ''
},
owner: {
email: '',
password: ''
}
}
}
And then, you simply use the jQuery "extend" method (req2 is your submmited object):
$.extend(true, req, req2);
I've create this fiddle for you!
-
Update
Nothing related to your question, but I've just noticed that you're passing an object with a similar structure of req.body to the Business class. However, there is no need to copy property by property manually - you can make, for example, a simple copy of req.body to pass as parameter:
var b = new Business($.extend({}, req.body));
or
var b = new Business(JSON.parse(JSON.stringify(req.body)));
You can't, really. You have two options;
Use a try/ catch:
try {
var b = new Business({
//
});
} catch (e) {
// Something wasn't provided.
}
... or you can define a helper function:
function get(path, obj) {
path = path.split('.');
path.shift(); // Remove "req".
while (path.length && obj.hasOwnProperty(path[0])) {
obj = obj[path.shift()];
}
return !path.length ? obj : null;
}
... you could then replace your use of req.body.address.street etc. with get('req.body.address.street', req).
See a demo here; http://jsfiddle.net/W8YaB/

Categories