Destructure array of objects, default value - javascript

I would like to set the default value of an object property if the value is undefined.
When destructing from the tags array, the name property, I would like to rename the property to colour, and set the default value if its undefined.
How can I do that?
I currently get name not defined with the code below:
const {
description,
categories,
id,
title,
>> tags: [{ name: colour= 'none' }], <<
organizer: [{ organizer: organiser }],
venue: { venue }
} = event;
This gives me colour is undefined
const {
description,
categories,
id,
title,
tags: [{name:colour = "none"}={name:"none"}]=[{name:"none"}],
organizer: [{ organizer: organiser }],
venue: { venue }
} = event;
Sample data:
const sample = {"tags":[{"name":"red","slug":"red","term_group":0,"term_taxonomy_id":125,
"taxonomy":"post_tag","description":"","parent":0,"count":1,"filter":"raw","id":125,"urls"}]}
or empty const sample = {"tags":[]}

Does this help?
var {x,y,z,t:[{name:colour = "none"}]=[{name:"none"}]} = {x:3,y:2,z:1,t:[{name:"gray"}]};
console.log(colour);//"gray"
If t does not exist in the object:
var {x,y,z,t:[{name:colour = "none"}]=[{name:"none"}]} = {x:3,y:2,z:1};
console.log(colour);//"none"
PS: It seems to be in your object "t" might be defined as an empty array, in that case:
var {x,y,z,t:[{name:colour = "none"}={name:"none"}]=[{name:"none"}]} = {x:3,y:2,z:1,t:[]};
console.log(colour);//"none"
PS2: Here is proof of concept from the sample data you provided:
var {x,y,z,tags:[{name:colour = "none"}={name:"none"}]=[{name:"none"}]} = {x:3,y:2,z:1,"tags":[{"name":"red","slug":"red","term_group":0,"term_taxonomy_id":125,
"taxonomy":"post_tag","description":"","parent":0,"count":1,"filter":"raw","id":125,"urls":"some"}]};
console.log(colour);//"red"
Although I should say the original example you post and the sample data you provide do not have identical structure. In your original post other properties like description etc are outside the tags key whereas in the sample you provide everything is inside the tags array.

Related

find property inside nested array javascript

I have an object that contains data to display information pulled from the Notion API. I can see the data but not sure how I can extract nested array inside the current array. My goal is to use the category property to create a filter but first I need to get the string to create the condition.
Here is what the data looks like currently. How would I go about to filter out name: "commissions":
resultsArray:
0:
properties
category:
id: "sdasd"
multi_select:
0:
id:"324234"
name: "commissions"
I have tried use find but it doesn't do what I expect. My suspicion is that I will have to loop over the nested array again.
You can use find inside find condition
like this :
data.resultsArray.find(item=>item.category.multi_select.find(select=> select.name === "commissions"))
const data = {
resultsArray: [
{
category: {
id: 'sdasd',
multi_select: [
{
id: '324234',
name: 'commissions',
},
],
},
},
],
};
const result = data.resultsArray.find(item=>item.category.multi_select.find(select=> select.name === "commissions"))
console.log(result)

Having issue with getting value from object variable. No errors showing

I created an array called animals containing two objects. I want to get a value from the name variable in the object animals and insert that value in a return statement in the map method. I used ${} to access the variable.
const Animals = [{
name: "Lion",
type: "Carnivore",
},
{
name: "Cow",
type: "Herbivore",
},
];
window.addEventListener("DOMContentLoaded", function() {
let display = Animals.map(function(item) {
return '<h1>${item.name}</h1>';
});
console.log(display);
});
Now I'm supposed to get in the console an array of two items containing the values of the variables -- the result should look like this ['<h1>Lion</h1>', '<h1>Cow</h1>']. But instead I get this ['<h1>${item.name}</h1>', '<h1>${item.name}</h1>']. As you can clearly see, for some reason the ${} was unable to access the variable and get the value. I don't know why this's happening. Console log shows no errors. Plz help me resolve this issue. Thanks in advance.
Check in your code instead of:
'<h1>${item.name}</h1>'
Should be:
`<h1>${item.name}</h1>`
Here is the documentation for Template literals (Template strings)
Demo:
const Animals = [{
name: "Lion",
type: "Carnivore",
},
{
name: "Cow",
type: "Herbivore",
},
]
const display = Animals.map(({ name }) => `<h1>${name}</h1>`)
console.log(display)
Variables inside ${...} structures are template/string literals syntax but in order for them to work they need to be enclosed with backticks instead of single/double quotes.
const animals=[{name:"Lion",type:"Carnivore"},{name:"Cow",type:"Herbivore"}];
window.addEventListener("DOMContentLoaded", function() {
const display = animals.map(function(item) {
return `<h1>${item.name}</h1>`;
});
console.log(display);
});
const Animals = [{
name: "Lion",
type: "Carnivore",
},
{
name: "Cow",
type: "Herbivore",
},
];
window.addEventListener("DOMContentLoaded", function() {
let display = Animals.map(function(item) {
return '<h1>'+item.name+'</h1>';
// return `<h1>${item.name}</h1>`;
});
console.log(display);
});

Creating an array within an object within an object

Using Javascript, how do I create an array within an object that's within an object, so that my value is stored at: main[1].type[1][0]
I have tried and my code which does not work is as follows:
let main = []
main[1] = {type: {1:['Value1', 'Value2']}, {2:['Value3', 'Value4']}};
console.log(main[1].type[0][1]);
I expect main[1].type[1][0] to be 'Value1' but it is undefined
You're not getting undefined. You have a syntax error. A comma should either be separating array values, or separating object entries. You have a comma here, in an object, so it is expected to have a key after it, not a {
main[1] = {type: {1:['Value1', 'Value2']}, {2:['Value3', 'Value4']}};
|
|
Remove the } and { around this comma
Remove the } and { around the comma so that {1:['Value1', 'Value2'], 2:['Value3', 'Value4']} becomes a single object with two keys:
const main = [];
main[1] = {type: {1:['Value1', 'Value2'], 2:['Value3', 'Value4']}};
console.log( main[1].type[1][0] );
First your declaration is wrong and will not works.
{type: {}, {}} isn't a valid JSON and you must wrap it into [] to create array of object {type: [{}, {}]}.
Also by adding a level you will have to ask for: main[1].type[0][1][0] to get the complet path to Value1
let main = []
main[1] = {type: [{1:['Value1', 'Value2']}, {2:['Value3', 'Value4']}]};
console.log(main[1].type[0][1][0])
Your problem is you can not create an object with a numbered object inside it you have to use the array notation var variableName = [/*variable values here separated by commas*/]
This will fix your problem:
let main = []
main[1] = {
type: [
['Value1', 'Value2'],
['Value3', 'Value4']
]
};
console.log(main[1].type[0][1]);
Breaking down your issue, an object must be "zero or more pairs of property names and associated values of an object." The second value in the question's code does not have a key, causing an uncaught SyntaxError.
Here's an object literal that returns your desired result:
const main = {
1: {
type: { 1: ['Value1', 'Value2'] },
otherType: { 2: ['Value3', 'Value4'] },
},
};
main[1].type[1][0]
=> "Value1"
Object initializer docs
Another option could be to use sparse arrays :
let main = [, { type: [, ['Value1', 'Value2'], ['Value3', 'Value4'] ] } ];
console.log(main[1].type[1][0]);

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

vuejs copying data object and removing property will remove the property from original object as well

I have a data object in vue that looks like this
rows[
0 {
title: "my title",
post: "my post text",
public: false,
info: "some info"
},
1 {
title: "my title",
post: "my post text"
public: true,
info: "some info"
},
2 {
title: "my title",
post: "my post text"
public: false,
info: "some info"
}
]
I then copy that object and remove certain properties if needed before posting the object to my backend like this:
var postData = this.rows;
postData.forEach(function(o) {
if (o.public === true) {
delete o.info;
}
});
var uploadData = {};
uploadData.blogpost = postData;
axios({
method: 'post',
url: myUrl,
responseType: 'json',
data: uploadData
})
The problem is that delete o.info; will also remove the property from my vm root data, and I dont understand why since I created a new varible/copied the root data into that one. So how can I remove certain object properties from my data before posting it without altering my root data vm in vue ?
You need to take a copy of your data by cloning it. There are various ways of cloning the data, I would recommend using lodash's function, cloneDeep
import _ from 'lodash'
...
postDataCopy = _.cloneDeep(postData)
Then you can modify postDataCopy as you like without modifying the original.
this is because in javascript objects are copied-by-reference which means though you are changing postData which actually is referencing to original address that holds the data i.e. rows. you can do this
postData = JSON.parse(JSON.stringify(rows))
You need to make a copy of your referenced variable.
// ES6
let copiedObject = Object.assign({}, originalObject)
it is because row is reference type and postData is pointing to same reference as row. To copy without reference (deep copy) you can use Object.assign if your object/array contains only value type ( like number, string , boolean etc) not reference type like Object or Array. If your Object contains reference type like object containing object then internal copied object will be reference type.
Example 1:
var user = {
name: "abc",
address: "cde"
};
var copiedUser = Object.assign({}, user);
it copies properties from user. So user and copiedUser are different object because user contains only value types
Example 2:
var user = {
name: "abc",
address: "cde",
other_info: { // reference type
country: "india"
}
};
var copiedUser = Object.assign({}, user);
Now it copies all properties from user but user contains other_info that is reference type(object). so changing copiedUser properties which are value type will not affect user but changing other_info of copiedUser or user will affect each other.
copiedUser.name ="new name"; // will not reflect in user
copiedUser .other_info.country = "new country"; // will reflect in user also
So Object.assign will copy to one level. If your object contains nested object or array you need to iterate and copy till last level.
Object.assign takes {} as well as [] also. so you can return array also.
eg:var copiedArray= Object.assign([], [1,3,4,5]);
So for your case I think you need to iterate your array till object then copy and push them in another array;
var rows = [
{
title: "my title",
post: "my post text",
public: false,
info: "some info"
},
{
title: "my title",
post: "my post text",
public: true,
info: "some info"
},
{
title: "my title",
post: "my post text",
public: false,
info: "some info"
}
];
var postData = [];
for(var i=0;i<rows.length;i++) {
postData.push(Object.assign({}, rows[i]));
}
Reactivity is caused by Observer _proto inside each object and array.
You can use the following object util as mixin if needed to remove ovservable hatch from each object.
const isEmpty = (value) => {
if (!value) return false;
if (Array.isArray(value)) return Boolean(value.length);
return value ? Boolean(Object.keys(value).length) : false;
};
const isNotEmpty = value => isEmpty(value);
const clone = (value) => {
if (!value) return value;
const isObject = (typeof value === 'object');
const isArray = Array.isArray(value);
if (!isObject && !isArray) return value;
// Removing reference of Array of values
if (isArray) return [...value.map(val => clone(val))];
if (isObject) return { ...value };
return value;
};
const merge = (parent, values) => ({ ...parent, ...values });
export {
isEmpty,
isNotEmpty,
clone,
merge
};
And in store getters .
import { clone } from '#/utils/object';
const getData = state => clone(state.data);
export default {
getData
}

Categories