How to update deep list in ImmutableJS? - javascript

Can anyone tell me what how to update 'value' by id in this structue in ImmutableJS?
map = {
list: [
{
id: 1,
value: 'update'
}
]
}

You can use the code below. However, it is not the best solution, because that will search all items in the list. If you can change your structure instead of List you can use OrderedMap.
var newData = map.set("list", map.get("list").map(data => data.get("id") === 1 ? data.set("value", "updatedValue") : data));

Related

Get values from objects in array with rest parameter

let newValues = user.info.socialMedia ? [...user.info.socialMedia] : []
So here we get several objects into the array that have an id key, and instead of the objects themselves I want to have only the id strings in this array. How can I get this working? I am quite new to Javascript, so it would be nice to get some help here.
I tried a for of then a for in loop to get the ids out of there and push them to the array, tho this does not work for my case.
instead of the objects themselves I want to have only the id strings
That sounds like a .map() operation, to project one array into another by applying a transformation to each object. Something like this:
let newValues = user.info.socialMedia ? user.info.socialMedia.map(s => s.id) : []
Or perhaps simpler:
let newValues = user.info.socialMedia?.map(s => s.id) ?? []
For example:
let user = {
info: {
socialMedia: [
{ id: 1, name: 'Ron' },
{ id: 2, name: 'Tammy' },
{ id: 3, name: 'Tammy 2' }
]
}
};
let newValues = user.info.socialMedia?.map(s => s.id) ?? []
console.log(newValues);

Find matching item across multiple store arrays in VueX

Currently when I want to find single item in an array that is in store I use this:
this.matched = this.$store.state.itemlist.find(itemId=> {
return itemId.id == "someid";
});
Lets says I want to go over multiple arrays to find the matching item given provided ID? Like i have itemlist1 itemlist2 itemgetter()... Some of the arrays are getters ( but I think it doesnt change much). So basically I want to search over different state and getter items in this component instead of searching over one as in example above.
if you just want to find if its exist in one the arrays you can simply write function like this
function find(search,...arrs){
return arrs.flat(1).find(item => item == search)
}
this function merge all arrays to one long array and search in it
example of usage
let a=[1,2,3,4]
let b=[5,6,7,8]
let c=[9,10,11,12]
let i=find(6,a,b)
console.log(i)
Using one object to group all the arrays, so that will be possible to iterate over them. The idea is something like below:
const store = new Vuex.Store({
state: {
itemsGroupArrays: {
items1: [{ id: 1, text: "item1 - 1" }, { id: 2, text: "item1 - 2" }],
items2: [{ id: 3, text: "item2 - 1" }, { id: 4, text: "item2 - 2" }]
}
},
getters: {
getItemByIdFromStateGroupArrays: state => (id) => {
let returnedItem = null;
Object.values(state.itemsGroupArrays).forEach((itemStateArray) => {
if (itemStateArray.some(item => item.id === id)) {
returnedItem = itemStateArray.find(item => item.id === id);
}
})
return returnedItem;
}
}
});

update nested Object data without changing Object Id

I am currently using array filters to update the nested object.
My structure is -
Category Collection -
{
name:Disease,
_id:ObjectId,
subCategory:[{
name:Hair Problems,
_id:ObjectId,
subSubCategory:[{
name: Hair Fall,
_id:ObjectId
},{
name: Dandruff,
_id:ObjectId
}]
}]
}
I want to update the subsubcategory with id 1.1.1 which I am doing by using array filters.
let query = { 'subCategories.subSubCategories._id': subSubId };
let update = { $set: { 'subCategories.$.subSubCategories.$[j]': data } };
let option = { arrayFilters: [{ 'j._id': subSubId }], new: true };
await Categories.findOneAndUpdate(query, update, option
This code is working fine but array filters change the object id of subsubCategory. Is there any other alternative to do so without changing the ObjectId.
Thanks in advance
You can loop over the keys which you are getting as payload and put inside the $set operator.
const data = {
firstKey: "key",
secondKey: "key2",
thirdKey: "key3"
}
const object = {}
for (var key in data) {
object[`subCategories.$.subSubCategories.$[j].${key}`] = data[key]
}
let query = { 'subCategories.subSubCategories._id': subSubId };
let update = { '$set': object };
let option = { 'arrayFilters': [{ 'j._id': subSubId }], 'new': true };
await Categories.findOneAndUpdate(query, update, option)
Problem is in $set line there you have not mentioned specific fields to be update instead subCategory.$.subSubCategory.$[j] will replace complete object element that matches the _id filter. Hence your _id field is also getting updated. You have to explicitly mention the field name after array element identifier. See example below:
Suppose you want to update name field in subSubCategories from Dandruff to new Dandruff. Then do this way:
let update = { $set: { 'subCategories.$.subSubCategories.$[j].name': "new Dandruff" } };
This will only update name field in subSubCategories array

JS Object {} advanced filtering

I have a huge chunk of data directly from the database, that data is stored in a JS object : {}, however I'm unable to use built-in JS's .filter function.
Avoid arrow functions as I'm using Vue.JS.
Example of JS Object:
0:
brand: "Brand A"
compatibilitySetIds:Array(3)
createdAt:"2018-08-13T09:07:50.772Z"
deletedAt:null
id:"e7915261-677d-4527-90c6-09b5170afca8"
model:"Model-1"
series:null
type:"A"
updatedAt:"2018-08-13T09:07:50.772Z"
1:
brand: "Brand B"
compatibilitySetIds:Array(3)
createdAt:"2018-08-13T09:07:50.772Z"
deletedAt:null
id:"e7915261-677d-4527-90c6-09b5170afca8"
model:"Model-51"
series:"S02"
type:"B"
updatedAt:"2018-08-13T09:07:50.772Z"
I need to be able to:
Filter by Model
Preferably filter also by Brand/Series/Type
Be able to sort asc/desc in all fields
What I currently have (works)
computed: {
filteredEquipment: function() {
if (this.search.selected === '' || !this.search.selected) {
return this.equipmentItems;
} else {
const model = this.search.selected;
console.log(model);
const filtered = this.equipmentItems.filter(function(item) {
return item.model === model;
});
return filtered;
}
},
},
PS.
Using Vue-JS along with TypeScript.
PPS.
I must filter on the client side, not on the server side.
I'm assuming that your data items are wrapped inside an array, since you have object keys "0" and "1", which seem to be indexes to me. Also you use filter yourself in your code.
You have a couple of choices here to use .filter().
So you can choose which best suites your coding style.
const data = [
{
brand: "Brand A",
compatibilitySetIds: [],
createdAt:"2018-08-13T09:07:50.772Z",
deletedAt:null,
id:"e7915261-677d-4527-90c6-09b5170afca8",
model:"Model-1",
series:null,
type:"A",
updatedAt:"2018-08-13T09:07:50.772Z"
},
{
brand: "Brand B",
compatibilitySetIds: [],
createdAt:"2018-08-13T09:07:50.772Z",
deletedAt:null,
id:"e7915261-677d-4527-90c6-09b5170afca8",
model:"Model-51",
series:"S02",
type:"B",
updatedAt:"2018-08-13T09:07:50.772Z"
}
];
//Specific one liner to filter all Model-1 models.
const AllModel_1Items = data.filter( item => item.model === 'Model-1' );
console.log( AllModel_1Items );
// Generic function with 3 parameters:
const filterProperty = ( source, property, value ) => source.filter( item => item[ property ] === value );
const allTypeA = filterProperty( data, 'type', 'A' );
console.log( allTypeA );
// Generic function usable with .filter()
const byProperty = ( property, value ) => item => item[ property ] === value;
const allBrandA = data.filter( byProperty( 'brand', 'Brand A' ));
console.log( allBrandA );
These functions can filter any property. Sorting asc/desc is just .reverse() the array after .sort().
If for some reason arrows can't be used or filter cannot be used, the same structure can be applied to a simple for loop to mimic .filter().
But since you use both .filter() and arrows in your own code, I'll assume that you can use them.
Object.keys(dbObject) this will convert into array. Then you should be able to use just all the other filter and etc. methods
You can use a loop for read array, and add conditions for filter your data, for example:
let dataFiltered = [];
let data = [
{
brand: "Brand A",
compatibilitySetIds:Array(3),
createdAt:"2018-08-13T09:07:50.772Z",
deletedAt:null,
id:"e7915261-677d-4527-90c6-09b5170afca8",
model:"Model-1",
series:null,
type:"A",
updatedAt:"2018-08-13T09:07:50.772Z",
},
{
brand: "Brand B",
compatibilitySetIds:Array(3),
createdAt:"2018-08-13T09:07:50.772Z",
deletedAt:null,
id:"e7915261-677d-4527-90c6-09b5170afca8",
model:"Model-51",
series:"S02",
type:"B",
updatedAt:"2018-08-13T09:07:50.772Z",
}];
//Use a loop for read array
data.forEach(function(item){
if(item.model === 'Model-1'){
//Add conditions after push item to dataFilter
dataFiltered.push(item);
}
})
console.log(dataFiltered);//In dataFilter is data filtered

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

Categories