How to change property values in an array Object? - javascript

I'm trying to change the values of each property in an array using a forEach function but not having any luck.
Here's my array:
this.panels = [
{ isRandomPanel : false },
{ isMyPanel : false },
{ isFavorite : false },
{ isEatable : false }
]
I'm trying to update the value of each property to true so finally I can get this:
isRandomPanel = true
isMyPanel = true
isFavorite = true
isEatable = true
I'm trying to use the forEach function but I'm stuck:
this.panels.forEach(panel => panel.isRandomPanel = true);
Does anyone know how to make this happen using pure Javascript, TypeScript or ES6?

If those are the only keys on the objects, you can iterate over Object.keys(panel) and set each panel[key] = true, like so:
var panels = [
{ isRandomPanel : false },
{ isMyPanel : false },
{ isFavorite : false },
{ isEatable : false }
];
// set all panel flags to true
panels.forEach(function (panel) {
Object.keys(panel).forEach(function (key) {
panel[key] = true;
});
});
console.log(panels);
Or, with shortened ES6 Syntax:
panels.forEach(panel => Object.keys(panel).forEach(key => panel[key] = true));

You need to itreate over the array, get each key from the object and set the value of that key to true. You can use Object.keys or for in loop to get the keys:
this.panels.forEach(panel => {
for(const key of Object.keys(panel))
panel[key] = true
})
OR
this.panels.forEach(panel => {
for(const key in panel)
panel[key] = true
})

As you are using ES 6, So following will work
panels.forEach(panel => Object.keys(panel).forEach(key => panel[key] = true));

Related

Remove all array of objects that contain same key and has at least one value true

Hi I have an array of objects which string starts with a specific prefix and if that key value is true then remove all the objects in an array that contains the same key(prefix)
below is the array of object:
const data = [{
field_name_key: "Recive_IsViaEmail",
fieldValue: false
},
{
field_name_key: "Recive_IsViaSMS",
fieldValue: false
},
{
field_name_key: "Sender_IsViaEmail",
fieldValue: false
},
{
field_name_key: "Sender_IsViaSMS",
fieldValue: true
},
]
here "Sender_IsViaSMS" contains true hence remove all the objects that start with the prefix key Sender_IsVia
Final result is this:
const data = [{
field_name_key: "Recive_IsViaEmail",
fieldValue: false
},
{
field_name_key: "Recive_IsViaSMS",
fieldValue: false
}
]
An inefficient but short solution would be to use Array.filter and set the condition of the callback to whether data contains an item with the same field_name_key property prefix and whose fieldValue property is true:
const data=[{field_name_key:"Recive_IsViaEmail",fieldValue:false},{field_name_key:"Recive_IsViaSMS",fieldValue:false},{field_name_key:"Sender_IsViaEmail",fieldValue:false},{field_name_key:"Sender_IsViaSMS",fieldValue:true}];
const res = data.filter(e => !data.find(f => f.field_name_key.split("IsVia")[0] == e.field_name_key.split("IsVia")[0] && f.fieldValue))
console.log(res)
Build up a list of the prefixes to remove first, then just run a filter.
I am not sure on how you are coming up with the prefix of a given field name however. Given your example you're expecting "Sender_IsViaSMS" to also purge "Recive_IsViaSMS". But you should be able to take this and adapt it as you see fit.
const data=[{field_name_key:"Recive_IsViaEmail",fieldValue:false},{field_name_key:"Recive_IsViaSMS",fieldValue:false},{field_name_key:"Sender_IsViaEmail",fieldValue:false},{field_name_key:"Sender_IsViaSMS",fieldValue:true}];
const prefixsToAxe = new Set();
// Having trouble with this part in your question, so ran with this, replace as you see fit
const determinePrefix = (field_name_key) => field_name_key.split('IsVia')[0];
for (const entryToAxe of data.filter(x => x.fieldValue === true)) {
const prefixToAxe = determinePrefix(entryToAxe.field_name_key);
prefixsToAxe.add(prefixToAxe);
}
const purged = data.filter(entry => {
const prefixInQuestion = determinePrefix(entry.field_name_key);
return !prefixsToAxe.has(prefixInQuestion);
})
console.log(purged)
You can create a function that first finds the entries to remove, then remove one by one:
const data = [{
field_name_key: "Recive_IsViaEmail",
fieldValue: false
},
{
field_name_key: "Recive_IsViaSMS",
fieldValue: false
},
{
field_name_key: "Sender_IsViaEmail",
fieldValue: false
},
{
field_name_key: "Sender_IsViaSMS",
fieldValue: true
},
]
const sanitizeData = (list) => {
// find entry keys to remove
const toRemove = list.reduce((prev, el) => {
if(el.fieldValue === true) return el.field_name_key.split('_')[0]
})
// remove
const removed = list.filter(el => {
return !toRemove.includes(el.field_name_key.split('_')[0])
})
return removed
}
console.log(sanitizeData(data))

Updating state as a nested object

I have this type of state in my app
state = {
abc: true,
array: [
{ id: 12345, done: false },
{ id: 10203, done: false },
{ id: 54321, done: false }
]
};
I am looking for a solution to the following problem: I need to change done property accordingly to passed id like in the following function when something like this handle(12345) is passed as an argument to handle function :
handle = id => {
this.state.array.map(e => {
if (e.key === id) {
this.setState({array: [
{ id: id, done: true },
{ id: 10203, done: false },
{ id: 54321, done: false }
]})
}
});
};
In simple words I need to change just one object in array based on provided id.
Thanks for any help or tips!
I'd write the handle method as:
handle = id => {
this.setState(prevState => {
const { array } = prevState;
return {
array: [
...array.filter(o => o.id !== id),
{id, done: true}
]
};
});
};
The idea here is that, remove the matching id from old state, and then add a new object to the array with id and done property as {id, done: true}.
Once you are allowed to restructure state to be hashmap instead of array:
state = {
abc: true,
array: {
12345: { done: false },
10203: { done: false },
54321: { done: false }
]
};
then you will be able to use power of spread operator:
let id = 12345;
this.setState({
array: {
...this.state.array,
[id]: {
...this.state.array[id],
done: true
}
}
});
Otherwise using array.map() seems to be the only option
You can use this Redux pattern to return a new array with the element in question being changed, while keeping your array immutable:
handle = id => {
const updatedArray = this.state.array.map(e => {
if (e.key === id) {
return { id: id, done: true };
}
else {
return e;
}
});
this.setState({array: updatedArray});
};
This keeps your data structures immutable while changing only what you need to change.
var newArray = this.state.array;
for(var i = 0; i < newArray.length; i++){
if(newArray[i].id === 12345) {
newArray[i].done = true;
}
}
this.setState({array: newArray});
By creating the newArray here you will be avoiding directly touching the state element, so you can change anything you want inside it afterwards you can set the state.

Check all object values inside Array javascript has boolean false

I have below object inside array
[
{
"age":32,
"test":true
},
{
"age":33,
"test":true
},
{
"age":35,
"test":false
}
]
I need to check if all values of test is false.
I have tried below code
Array.isArray(obj.map((message,index) => {
if(message.test !== message.test){
//trigger when all values are false
}
}))
How to achieve this?
You can use every from Array prototype:
let areAllFalse = array.every(x => x.test === false);
You can also you filter from array prototype...
const filtered = array.filter(a => a.test === true)
or the less verbose
const filtered = array.filter(a => a.test)

Object push Firebase, how to remove key names from pushed items

I have this Object.key code that pushes all items:
const cloned_items = [];
Object.keys(items).sort().map(key => {
let item = {
[`item-${uid}`]: {
item: false
}
}
cloned_items.push({ ...item });
});
database.ref('/app/items').update({
...cloned_items
})
but this produces following result:
"0" : {
"timeslot-87dah2j" : {
item: false
}
},
"1" : {
"timeslot-7s1ahju" : {
item: false
}
}
instead of:
"timeslot-87dah2j" : {
item: false
},
"timeslot-7s1ahju" : {
item: false
}
any idea ?
It seems like you want to create a plain object, not an array.
In that case:
const cloned_items = Object.assign(...Object.keys(items).map(uid =>
({ [`item-${uid}`]: {item: false} })
));
NB: sorting is of no use when creating an object -- its keys are supposed to have no specific order.
You're creating an array of objects. Seems like you want to use .reduce() to create a single object from the array.
const cloned_items = Object.keys(items).sort().reduce((obj, key) =>
Object.assign(obj, { [`item-${uid}`]: { item: false } })
, {});
Your code doesn't show where uid is coming from, but I assume you meant key there, along with timeslot instead of item.
You may find Object.defineProperty to be cleaner, though you'll need to set up the property descriptor as you want it.
const cloned_items = Object.keys(items).sort().reduce((obj, key) =>
Object.defineProperty(obj, `item-${uid}`, {value:{item: false}})
, {});

Filtering an object based on its values using lodash

How would I use lodash to get the following output ?
input = {
'property1' : true,
'property2' : false,
'property3' : false
}
// only pick those properties that have a false value
output = ['property2', 'property3'];
I currently have the following in place:
var output = [];
_.forEach(input, (value, key) => {
if (value === false) {
output.push(key);
}
});
Plain JS you can do:
var output = Object.keys(input).filter(function(k) { return input[k] === false })
You can do something like that using lodash:
const output = _.keys(_.pickBy(input, function(value, key) {return !value }));

Categories