How to check if array attribute from JSON object is empty? - javascript

I've this kind of JSON object :
sections:
[
{
"id":1,
"title":"Description du projet",
"content":[
{
label:'Type de projet',
type:'select',
values:[
{
label:'Achat',
options:[
{
label:'Neuf'
},
{
label:'Neuf + travaux'
},
{
label:'Ancien'
},
{
label:'Ancien + travaux'
},
{
label:'Terrain'
},
{
label:'Terrain + construction'
}
]
},
And I would like to check if the "options" array is define or not in order to build different component in each case.
Is it possible ? If yes can you tell me how ?
Thank you in advance

Iterate each array from "sections" until "values", then we will do the checking there. See these code:
sections.forEach(section =>{
section.content.forEach(c => {
c.values.forEach(value =>{
if (!value.options) {
// "options" array is undefined.
return;
}
// "options" array is defined, build different components here.
});
});
});

You can use lodash to do all the undefined or exists checks. Check out the library here
Coming to your question, using lodash I'd do something like this:
import _ from 'lodash';
let options = _.get(a, ['sections','0','content', '0', 'values', '0', 'options']);
if(!_.isUndefined(options)){
//do your stuff
}
You can do this in many ways using lodash. You can also get default value back if the path doesn't exist.

Related

Saving array and objects within said array

I am trying to make a simple to do app using vue.js, I want to try and save my to-dos that are set in the array so that when I reset the site, they still remain. Looking through some of the documentation I arrived at this:
data() {
return {
array: [
{id: 1, label: 'learn vuejs'},
]
}
},
methods: {
persist() {
localStorage.array = this.array;
alert('items saved')
}
},
mounted() {
if (localStorage.array && localStorage.array.id) {
this.array = localStorage.array;
this.array[id] = localStorage.array.id;
}
},
while this does save my array to localStorage, IT DOES NOT THE OBJECTS WITHIN. When I check localStorage in the console it shows :
array: "[object Object]"
anyone knows how to save the items within the array? if you do please explain it to me.
You need to store them as string. So localStorage.array = JSON.stringify(this.array), and when fetching from localStorage this.array = JSON.parse(localStorage.array);

Object spread inside of new array

I have a Node.js program that is using Mongo Atlas search indexes and is utilizing the Aggregate function inside of the MongoDB driver. In order to search, the user would pass the search queries inside of the query parameters of the URL. That being said, I am trying to build a search object based on if a query parameter exists or not. In order to build the search object I am currently using object spread syntax and parameter short-circuiting, like so:
const mustObj = {
...(query.term && {
text: {
query: query.term,
path: ['name', 'description', 'specs'],
fuzzy: {
maxEdits: 2.0,
},
},
})
}
This is a shortened version, as there are many more parameters, but you get the jest.
In a MongoDB search query, if you have multiple parameters that must meet a certain criteria, they have to be included inside of an array called must, like so:
{
$search: {
compound: {
must: [],
},
},
}
So, in order to include my search params I must first turn my mustObj into an array of objects using Object.keys and mapping them to an array, then assigning the searches 'must' array to the array I've created, like so:
const mustArr = Object.keys(mustObj).map((key) => {
return { [key === 'text2' ? 'text' : key]: mustObj[key] };
});
searchObj[0].$search.compound.must = mustArr;
What I would like to do is, instead of creating the mustObj and then looping over the entire thing to create an array, is to just create the array using the spread syntax and short-curcuiting method I used when creating the object.
I've tried the below code, but to no avail. I get the 'object is not iterable' error:
const mustArr = [
...(query.term && {
text: {
query: query.term,
path: ['name', 'description', 'specs'],
fuzzy: {
maxEdits: 2.0,
},
},
})
]
In all, my question is, is what I'm asking even possible? And if so, how?
Corrected based on #VLAZ comment:
while spread with array [...(item)], item has to be array (iterable).
When you use short-circuit, the item as below,
true && [] ==> will be `[]` ==> it will work
false && [] ==> will be `false` ==> wont work (because false is not array)
try some thing like (Similar to #Chau's suggestion)
const mustArr = [
...(query.term ? [{
text: {
query: query.term,
path: ['name', 'description', 'specs'],
fuzzy: {
maxEdits: 2.0,
},
},
}] : [])
]

forEach function in typescript

I am working with graphql returned data that looks like this:
"userRelations": [
{
"relatedUser": {
"id": 4,
"firstName": "Jack",
"lastName": "Miller"
},
"type": "FRIEND"
},
{
"relatedUser": {
"id": 3,
"firstName": "Rhena",
"lastName": "Tahoma"
},
"type": "CONTACT"
}
]
I had to separate all those items which had the type: "FRIENDS". I did this and it worked perfectly:
var friendArray = new Array();
for (let i in data.users.nodes[0].userRelations) {
if (data.users.nodes[0].userRelations[i].type == "FRIEND")
{
friendArray.push(data.users.nodes[0].userRelations[i]);
}
}
However, I read that using for loops and for in is not a good idea. Is there any other way to iterate and check all the objects without for loops? I tried using this but it doesn't give the correct results:
data.users.nodes[0].userRelations.forEach((object: Object)=> {
if (data.users.nodes[0].userRelations.type == "FRIEND")
{
friendArray.push(data.users.nodes[0].userRelations.object);
}
})
The friendsArray remains empty. What am I missing out?
Edit:
After filtering the friends data, I want to render some items by mapping. I was trying to do something like this:
data.users.nodes[0].userRelations.map()
data.users.nodes[0].userRelations.filter(({ type }) => type === 'FRIEND').map(/*code*/)
but this gave me an error that:
Binding element 'type' implicitly has an 'any' type.ts(7031)
In your case I would use filter:
var result = data.users.nodes[0].userRelations.filter(element=>element.type=="FRIEND");
First of all, using a for loop there is fine.
If you want to use foreach, you'll need to use the object element you create in the forEach callback. That's the advantage of using foreach.
data.users.nodes[0].userRelations.forEach((object: Object)=> {
if (object.type == "FRIEND")
{
friendArray.push(object);
}
})
If you want to improve the function, you may want to use a .filter, which is probably the cleanest way of solving this.
Have a look at array.filter(), you can do const friends = data.users.nodes[0].userRelations.filter(userRelation => userRelation.type === 'FRIEND") but to your current code, you could change your if statement to be - if(object.type==='FRIEND')
data.users.nodes[0].userRelations.forEach((o: Object)=> {
if (o.type == "FRIEND")
{
friendArray.push(o);
}
})

Change property in array with Spread Operator returns object instead of array

I want to change the property of an object similar to this, this is a simplified object with a few properties of the original:
state = {
pivotComuns: [
{
id: 1,
enabled : true
},
{
id: 2,
enabled : true
}
],
otherProperties : "otherProperties"
}
I'm changing the state of enabled like this:
state = {
...state,
pivotColumns: {
...state.pivotColumns,
[2]: {
...state.pivotColumns[2], enabled: !state.pivotColumns[2].enabled
}
}
}
It works, but instead of return an array like I is the pivotComuns property it returns an object, "notice that I change [] for {}":
state = {
pivotComuns: {
{
id: 1
enabled : true
},
{
id: 2,
enabled : true
}
},
otherProperties : "otherProperties"
}
What I'm doing wrong, I need to keep that property an array.
Very late post, but for future reference, you could do the following:
state = {
...state,
pivotColumns: state.pivotColumns.map(pc =>
pc.id === 2 ? {...pc, enabled:!pc.enabled} : pc
)
}
The advantage is that you will not change the object referenced in the "old array", you will instead insert a new object in its place. So if you would like to go back and forth in the state you can now do so.
example:
https://codepen.io/anon/pen/JyXqRe?editors=1111
I don't believe you can use the spread operator in such a way and in fact wouldn't recommend it if you could because it creates very hard to read code. There is a much simpler solution that I use on a daily basis when it comes to updating a key/value on an object where the value is an array:
var state = {
pivotColumns: [
{
id: 1,
enabled : true
}, {
id: 2,
enabled : true
}
],
otherProperties : "otherProperties"
}
var clonedPivotColumns = state.pivotColumns.slice();
clonedPivotColumns[1].enabled = !state.pivotColumns[1].enabled;
state = {
...state,
pivotColumns: clonedPivotColumns
}
this will get you the right results and will not cause any mutations.
working pen
http://codepen.io/finalfreq/pen/ggdJgQ?editors=1111

Unshift from object list without using delete?

If I can access an object from an object using list[value][index], how can I delete or unshift that object from list without using delete? (since that isn't possible in an object list)
My object looks like this:
var list = {
'test1': [
{
example1: 'hello1'
},
{
example2: 'world1'
}
]
'test2': [
{
example1: 'hello2'
},
{
example2: 'world2'
}
]
};
After deleting an object, I want it to look like this:
var list = {
'test1': [
{
example1: 'hello1'
}
]
'test2': [
{
example1: 'hello2'
},
{
example2: 'world2'
}
]
};
When I use delete, it looks like this:
var list = {
'test1': [
{
example1: 'hello1'
},
null
]
'test2': [
{
example1: 'hello2'
},
{
example2: 'world2'
}
]
};
You can remove the object from list by setting the value of list[key] to undefined. This won't remove the key, however - you'd need delete to do that:
list['test1'] = undefined; // list is now { test1: undefined, test2: [ ... ]}
delete list['test1']; // list is now { test2: [ ... ] }
Is there a particular reason you don't want to use delete? It won't make a difference if you're just checking list['test1'] for truthiness (e.g. if (list['test1']) ...), but if you want to iterate through list using for (var key in list) or something like that, delete is a better option.
EDIT: Ok, it looks like your actual question is "How can I remove a value from an array?", since that's what you're doing - the fact that your array is within an object, or contains objects rather than other values, is irrelevant. To do this, use the splice() method:
list.test1.splice(1,1); // list.test1 has been modified in-place
(Rewritten for corrected question.)
You can write:
list[value].splice(index, 1);
to delete list[value][index] and thereby shorten the array by one. (The above "replaces" 1 element, starting at position index, with no elements; see splice in MDN for general documentation on the method.)
Here is an example using splice:
http://jsfiddle.net/hellslam/SeW3d/

Categories