How to find object which id is not available in another array - javascript

I have 2 Array of objects. In which one is the original array, and another array contains the modified array. The modified array can contain new objects, edited object, or deleted object in settingValueDtoList
Currently, I am writing code for a new record in settingValueDtoList. If I am adding some new object in any settingValueDtoList then its id will be like a0, or a1 or a2 like this. I am just iterating both arrays and checking if id is not present in the original array, it means it is a new object, I want to push that object into my addSettingArray variable.
How can I fetch that new record whose id is not present in the original array?
This is what I tried.
compareSetting(settingArray: Array<any>) {
console.log('abc', this.settingObject)
console.log('settingArray',settingArray)
let settingIndex = 0;
this.settingObject.forEach(unmodifiedSetting => {
let modifiedSetting = settingArray[settingIndex];
modifiedSetting.settingValueDtoList.forEach(editedSettingValue => {
unmodifiedSetting.settingValueDtoList.forEach(uneditedSettingValue => {
if(editedSettingValue.id != uneditedSettingValue.id) {
this.addSettingArray.push(editedSettingValue);
}
});
})
settingIndex++;
})
console.log('add', this.addSettingArray)
}

Try like this:
compareSetting(settingArray: Array<any>) {
console.log('abc', this.settingObject)
console.log('settingArray',settingArray)
let settingIndex = 0;
this.settingObject.forEach(unmodifiedSetting => {
let modifiedSetting = settingArray[settingIndex];
modifiedSetting.settingValueDtoList.forEach(editedSettingValue => {
let isNewEntry = true;
unmodifiedSetting.settingValueDtoList.forEach(uneditedSettingValue => {
if(editedSettingValue.id == uneditedSettingValue.id) {
isNewEntry = false;
}
});
if (isNewEntry){
this.addSettingArray.push(editedSettingValue);
}
})
settingIndex++;
})
console.log('add', this.addSettingArray)
}
Edit:
More abstract for better understanding:
array1.forEach(entry1 =>
{
let isNewEntry = true; // says if entry1 is not present in array2
array2.forEach(entry2 =>
{
if(entry1.id == entry2.id)
{
isNewEntry = false; // the entry1 was found in array2
}
});
if (isNewEntry)
{
// the entry1 was not found in array2 - do whatever you want here
}
});

Related

How to delete a Firestore field inside a map that is an array element?

I would like to be able to delete varToDelete field inside a map if a condition occurs.
For some reason, the code to delete it is reached, but nothing is happening
Here is the structure of my document:
loc [
{
var1,
var2,
varToDelete
},
{
var1,
var2,
varToDelete
}
]
So, I started to think about this code:
await db.runTransaction(async (t) => {
var locRef = db.collection('documents').doc('123-456');
var locSnapshot = await locRef.get();
var loc = locSnapshot.data().loc;
loc.forEach(l => {
if (typeof l.varToDelete !== 'undefined') {
t.update(locRef, {
"varToDelete": admin.firestore.FieldValue.delete()
});
}
});
});
"varToDelete": admin.firestore.FieldValue.delete()
This will delete a field 'varToDelete' in the document itself. There is not direct method to delete a field from maps in an array. You must read the doc, remove that property from the objects and update the document with the whole new 'loc' array.
const newArr = locSnapshot.data().loc.map(({varToDelete, ...rest}) => rest)
t.update(locRef, {loc: newArr})

How to filter an array by two indvidual strings from an object?

I'm working on a project where I need to filter 13 items by two different select box values, and I'm getting stuck on persisting the filter.
I have two select boxes that I've selected like so:
let pickupLocation = document.querySelector("#pa_location"); //values are 'complete-set', 'neck', 'bridge'.
let pickupType = document.querySelector("#pa_type1"); // Values are 'soapbar', 'dogear', 'short'.
What's Working:
I'm initializing an object like so:
const activeFilters = {};
To populate the values like so:
//Persist the Complete Set / Single
pickupLocation.addEventListener("change", function () {
if (pickupLocation.value === "complete-set") {
activeFilters.location = "set";
} else {
activeFilters.location = "single";
}
});
pickupType.addEventListener("change", function () {
if (pickupType.value === "soapbar") {
activeFilters.type = "soapbar";
} else if (pickupType.value === "dogear") {
activeFilters.type = "dogear";
} else {
activeFilters.type = "short";
}
});
// Returns something like
// {location: single, type: dogear}
I'm trying to filter an array of input elements by their value. I have 13 inputs each with a value containing words like set, single, dogear, soapbar etc.
Where I'm stuck:
I have a filter function that I'm trying to filter the values of these inputs by two values of the activeFilters object:
const performFilter = (covers) => {
let results;
let filteredValues = Object.values(activeFilters);
filteredValues.forEach((value) => {
results = covers.filter((cover) => cover.value.indexOf(value) !== -1);
});
return results;
};
The problem is my function is returning only one of the two words. For instance, if the my activeFilters object is {location: set, type: dogear} the filtered results array contains only one of them. Where am I going wrong?
Edit:
This function returns all inputs that match one of the activeFilters, and I apologize if I wasn't clear above, but I'd like it to match ALL of the Active Filters. Is this possible with the function below?
const performFilter = (covers) => {
let results = []; // initialise the array
let filteredValues = Object.values(activeFilters);
filteredValues.forEach((value) => {
let res = covers.filter((cover) => cover.value.indexOf(value) !== -1);
results.push(...res);
});
console.log(results);
};
CODEPEN:
Codepen!
const performFilter = (covers) => {
let results = []; // initialise the array
let filteredValues = Object.values(activeFilters);
filteredValues.forEach((value) => {
let res = covers.filter((cover) => cover.value.indexOf(value) !== -1);
// push the value it find individually
// you were overriding the previous value with result = filter()
results.push(...res);
});
return results;
};
// according to Edited question
const performFilter = (covers) => {
let results = []; // initialise the array
let filteredValues = Object.values(activeFilters);
return covers.filter((cover) => filteredValues.every(value => cover.value.indexOf(value) !== -1));
};
I'm not sure if I understood clearly your question, so feel free to comment it.
First, I suggest you to filter your covers array and inside the filtering function iterate through your selected filters. This is because the filter function returns the array already filtered and so you don't need to assign it to a result variable or things like that. So based on that, try this:
const performFilter = (covers) => {
let results;
let filteredValues = Object.values(activeFilters);
const filteredCovers = covers.filter((cover) => {
return cover.value.split("-").some((tag) => filteredValues.includes(tag))
});
console.log(filteredCovers)
};

Return array value from produce function | immer.js

I am using immer.js to perform operations on arrays in the state.
Arrays: basicRecipe and recipeBasicRecipe.
I am modifying the draft.basicRecipe in the produce function. My objective is to return the updated "draft.basicRecipe" value and store the same in temparray1.
let temparray1 = produce(state, draft => {
draft.basicRecipe = draft.basicRecipe.map(item => {
let element = draft.recipeBasicRecipes.find(e => e._id === item._id);
console.log(element);
if (element) {
item.details = item.details.map(e => {
let detail = element.details.find(d => d._id === e._id);
if (detail) {
e.rate = detail.rate;
}
return e;
});
}
return item;
});
return draft.basicRecipe;
});
console.log(temparray1);
When I return the draft I am able to see updated basicRecipe nested in output.
I am getting the below error when I try to return the array i.e draft.basicRecipe
[Immer] An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft
This code is a mess. You are using map which returns a new array but you're also trying to mutate the original draft object.
This is still unreadable and confusing, but at least by using forEach instead of map we are just mutating and not trying to do two things at once.
let temparray1 = produce(state, (draft) => {
draft.basicRecipe.forEach((item) => {
let element = draft.recipeBasicRecipes.find((e) => e._id === item._id);
if (element) {
item.details.forEach((e) => {
let detail = element.details.find((d) => d._id === e._id);
if (detail) {
e.rate = detail.rate;
}
});
}
});
});

javascript cannot access array methods on push

I have a react app that pulls data from firebase. It adds data to the array fine. But cannot be accessed. calling the index returns undefined and length of array is 0. but when you print the array the console shows there is an element inside. Whats going on?
componentWillMount() {
itemsRef.on('value', (snapshot) => {
let items = snapshot.val();
let keys = Object.keys(items);
for(var i = 0; i < keys.length; i += 1) {
let k = keys[i];
let name = items[k].name;
let start = items[k].start;
this.state.timers.push( {
name: name,
start: start
} );
}
});
console.log(this.state.timers); // shows an array with stuff in it
this.setState({timers: this.state.timers}); // timers dont get added
// you cant even access elements in the array.
// ex: this.state.timers[0] returns undefined, but the console shows that it exists when the whole array is printed.
}
You shouldn't mutate directly your state like you do in the `this.state.timers.push({})``
You should do something like that:
itemsRef.on('value', (snapshot) => {
const items = snapshot.val();
this.setState({
timers: [
...this.state.timers,
...Object
.keys(items)
.map(key => {
const { name, start } = items[key];
return { name, start };
}),
],
});
});
You shouldn't push directly to the state. Instead you should to something like this:
ES6 variant
const timers = [...this.state.timers];
timers.push({ name, start });
this.setState({ timers })

Draft.js. How to get all entities data from the ContentState

From official docs I know about 2 methods: get entity by its key and get last created entity. In my case, I also need a method to access all entities from current ContentState.
Is there any method that could perform this? If not, is there a one that can provide all entities keys?
const getEntities = (editorState, entityType = null) => {
const content = editorState.getCurrentContent();
const entities = [];
content.getBlocksAsArray().forEach((block) => {
let selectedEntity = null;
block.findEntityRanges(
(character) => {
if (character.getEntity() !== null) {
const entity = content.getEntity(character.getEntity());
if (!entityType || (entityType && entity.getType() === entityType)) {
selectedEntity = {
entityKey: character.getEntity(),
blockKey: block.getKey(),
entity: content.getEntity(character.getEntity()),
};
return true;
}
}
return false;
},
(start, end) => {
entities.push({...selectedEntity, start, end});
});
});
return entities;
};
How I get the all entities keys:
const contentState = editorState.getCurrentContent()
const entityKeys = Object.keys(convertToRaw(contentState).entityMap)
result:
[0, 1]
then you can call the getEntity(key) method to get the responding entity.
this is how convertToRaw(contentState) looks:
Bao, You will find it inside key called 'blocks'.
convertToRaw(contentState).blocks.map(el=>el.text)
It will give you an array of raw text.
Unfortunatelly your suggested way using convertToRaw doesnt work because it reindexes all keys to ["0", .., "n"], but the real keys differ when you act with the editor. New ones > n will be added and unused will be omitted.
const rawState = convertToRaw(contentState)
const { entityMap } = rawState;
This entityMap will have list of all entities. But this is an expensive conversion. Because, it will convert whole thing to raw. A better way is loop through blocks and check for entity.
You'll have to look at every character:
const { editorState } = this.state; // assumes you store `editorState` on `state`
const contentState = editorState.getCurrentContent();
let entities = [];
contentState.getBlockMap().forEach(block => { // could also use .map() instead
block.findEntityRanges(character => {
const charEntity = character.getEntity();
if (charEntity) { // could be `null`
const contentEntity = contentState.getEntity(charEntity);
entities.push(contentEntity);
}
});
});
Then you could access it via:
entities.forEach((entity, i) => {
if (entity.get('type') === 'ANNOTATION') {
const data = entity.get('data');
// do something
}
})

Categories

Resources