I'm creating a To-Do list app, pretty basic and I copied the idea from Youtube (still learning JS). So, each time you add a new To-Do it's stored (just the text you typed and whether it's done or not) in an array and the HTML element is added, everything's good until here.
The problem begins when I try to delete that element from the array. Each item (To-do) has an ID which is basically the index where it's stored in the array, so I coded array.splice(item.id, 1) and It works great if you delete the items patiently one by one, but if you click the delete button faster the items deleted in the array doesn't match, it's like the index passed messes up. I was wondering if I could make like a wait until the current delete() function ends or something like that. Btw the list container has an eventListener and if the delete button of any item was clicked it runs the delete() function passing the item by e.target.parentElement (which is the item container).
I want the array for a localeStorage. Thanks!
First time posting and English isn't my first language, sorry for any mistake.
Great question. So .splice() is indeed the Array method you want to call, but it doesn't quite use the syntax you're expecting.
First of all, I'm going to point you to the MDN docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
MDN is managed by Mozilla, and is an authoritative source on most things javascript-in-the-browser. If you're just getting started with javascript, that resource will be invaluable. The MDN documentation is some of the best written technical documentation out there, and is largely written so that people with minimal experience in the language can understand them.
That being said, let's go over what Array.splice is actually doing.
So you have an array of todos:
const todos = [] // Array of to-dos
You want to delete one of the the todos, and you have access to the id. I'm going to assume your Todos have a shape similar to this:
const todo = {
id: 1 // number
name: 'my todo' // string
description: 'my todo description' // string
}
In order to delete an element from this array, given the id of the item you're deleting, you would actually need to do the following:
1) Find the location in the array of the todo that has the id you are looking for.
2) Splice that element out of the array using the index you just found.
Let's see how to do that:
function removeItemFromTodos(itemId, todos) {
// find the index of the todo with the id you are looking for
const indexOfTodoToDelete = todos.findIndex((todoInArray) => todoInArray.id === itemId));
// remove that todo:
todos.splice(indexOfTodoToDelete, 1) // delete the todo
}
Okay, so let's unpack that:
First, the findIndex method loops over the array. It will start at index 0, and work up until it reaches the end of the array. If the item it is currently looking at has an id that matches the id we are looking for, then the function will immediately return the index of that todo's location in the array, and stop searching in the array.
Once you have the index, you can delete the item. The splice function takes in the location that you want to start cutting elements as the first argument, and the number of elements you want to cut as the second argument. The splice method returns the elements that were deleted. So it is actually mutating the array in place, and not making a copy of it in memory to perform its operation.
Let me know if this solution doesn't work for you or if it isn't clear!
Related
I am adding the new task using following javascript code:
function addTask(name, important){
alert(important);
const newTask = {id: "todo" + nanoid(), name:name, completed:false, important:important, checked:false};
setTasks([...tasks, newTask]);
console.log(setTasks)
}
Now, I would like to add the last task on the first place of the application. May I ask please how to make it possible?
setTasks([newTask, ...tasks]);
Is the cleanest way to add items in front, however later on it may prove inconsistent (after saving into db for example and retrieving the list from db), personally I would use array.sort() method and sort the array by creation date or / and by "important" key. This way, no matter how you push an item into array, they will be always in correct / needed order.
I would like to update the completed property of an object in an array in Firestore, but I have no idea how to reach that specific element in the array. The image will show the structure.
I have come up this far but don't know how to choose, for example, item 1 in the array. I was thinking of using its ID (it has an id property) but don't know how to get there.
const businessRef = db.collection('approvedBusinesses').doc(businessId)
try {
businessRef.update({
[`bookings.${currentDate} ????? `]: true // what to add after currentDate?
})
By the way, this is how the array was created (and how other objects are pushed to it)
const bookingObj = {
carro: 'PASSA_CARRO',
completed: false,
userId: userObject.uid,
}
businessRef.update({
[`bookings.${currentDate}`]: firebase.firestore.FieldValue.arrayUnion(bookingObj),
})
Firestore does not have an operation that allows you to update an existing item in an array by its index.
To update an existing item in the array, you will need to:
Read the entire document into your application.
Modify the item in the array in your application code.
Write back the entire array to the document.
I'm pretty sure this has been asked before, so let me see if there's an answer with an example.
Also see:
How to remove an array element according to an especific key number?
Simple task list ordering - how to save it to Firebase Firestore?
How to update only a single value in an array
How to update an "array of objects" with Firestore?
i've been googling around about how to add an object into an array in firestore, and found the arrayUnion() able to add an object into firestore array, but it only add the object into last index of array, but how to add it into first index of array?
//add "greater_virginia" into last index of array
washingtonRef.update({
regions: firebase.firestore.FieldValue.arrayUnion("greater_virginia")
});
//how to add "greater_virginia" into first index of array?
its basically same as arrayUnion but instead of add it into last index, i want to add it into first index of array.
If Firestore arrays behave anything like realtime-database arrays, then they don't actually exist. As far as I know, they are store as maps, like:
{
0: "first element",
2: "second and so on",
}
You can probably see how an unshift would be a big transformation. In fact, firestore doesn't let you do this, saying "...in order to avoid some of the issues that can arise in a multi-user environment, you'll be adding them with more of a set-like functionality".
With that in mind, this problem is usually solved at the application level by fetching the array, mutating it as needed, then setting the whole thing.
Bit of further reading https://firebase.googleblog.com/2018/08/better-arrays-in-cloud-firestore.html
PS: be careful with the arrayUnion operator, because it actually performs a add to set
Firestore doesn't offer any way to modify items of array fields by index. arrayUnion will only ever append to the end of the array if the element doesn't already exist.
If you want to modify an array by index, you will have to read the document, modify the array in memory to appear how you want, then write the modified array back to the document.
In the javascript, there are two arrays:tags[] and tags_java[]. I use .splice to delete certain items, which of the same index in the two arrays. The tags[] works fine, but tags_java doesn't, it seems always delete the last item.
Here is the code and the jsfiddle link.
var tag = $(this).text();
var index = $.inArray(tag, tags);
tags.splice(index,1);
tags_java.splice(index,1);
Nah, both don't work, because you're not actually finding the correct index of your tag.
Why not? Because $(this).text() includes the delete mark you added, Ă— - e.g. "MorningĂ—". Since that's not in your tags array, index will be -1. tags.splice(-1, 1); will remove 1 item from the end of the array.
In general, it's never a good idea to use presentation text (i.e. the text of your tag element) as data (e.g. using that text as a lookup value in an array). It's very likely that it'll be broken when something changes in the presentation - like here. So a suggestion would be to store the data (what you need to look up the tags) as data - e.g. using the jQuery-provided data() API - even if it seems redundant.
Here's a quick example - just adding/replacing two lines, which I've marked with comments starting with "JT": JSFiddle
Now, instead of looking up by $(this).text(), we're looking up by the data value "tagValue" stored with $(this).data() - that way, the lookup value is still bound to the element, but we're not relying on presentation text.
If the tag is not in the tags array, $.inArray will return -1, which would then cause the last item to be deleted.
You have to make sure that the item is actually in the array.
I'm using Knockout-sortable to drag-and-drop/sort records in my table, but I've run into a problem. I have no clue how to keep track of the position in the sort index of an element. (I.e. element A, B and C appear in that order and have 1,2,3 as index respectively, but if B gets dropped above A the correct index would be 2,1,3)
Nothing in my code is custom: I just include knockout-sortable and it's plug and play. I usually always include a code snippet, but I don't feel that's useful. The only thing I know is that I'm probably gonna need a ko.computed(), but I have no idea what to fill it in with.
If you look at example http://jsfiddle.net/rniemeyer/Jr2rE/, you can see that the plug-in works by updating an observable array of data. Because of this, you don't have to keep track of the index value. The order of the records, technically, gives you all the information you need.
That being said, I ran into the same issue in last year. To solve my problem, I added a consecutively numbered index property to each object in my observable array. Then, when the sortable plug-in re-arranged the contents of the observable array, I just had to read out the new index property to know the sort order.