When I have an array and I use splice
to remove, let's say, the last element of the array. Is there a chance to create for example a button and when I click on it, it undoes the deleted action? Like using Ctrl + Z when write code and jump back in time? That means give me back the deleted element with all its characteristics?
When I have an array and I use splice
to remove, let's say, the last element of the array. Is there a chance to create for example a button and when I click on it, it undoes the deleted action? Like using Ctrl + Z when write code and jump back in time? That means give me back the deleted element with all its characteristics?
- 1 The 'deleted' element has to e back in exactly the same position as before the deletion? – kind user Commented Mar 20, 2017 at 20:43
- 2 why not to have an array of objects with one key to be "active" and instead of splicing, just set it false – binariedMe Commented Mar 20, 2017 at 20:45
- 1 @binariedMe This idea may be fine. Another question - does this array include duplicates? – kind user Commented Mar 20, 2017 at 20:49
- 1 Instead one can always go for saving the spliced elements in a trash array with its index, preserved. and thats how you can always undo it accordingly. Although you have to be careful with reinsertion of element in the original array. – binariedMe Commented Mar 20, 2017 at 20:50
- 1 @DerickKolln Check my answer. – kind user Commented Mar 20, 2017 at 21:13
4 Answers
Reset to default 4Array.splice
allows you to delete or insert elements, it also returns the removed elements when deleting. If you capture the deleted elements you can easily add them back:
let arr = [1,2,3,4,5,6];
// remove 1 element from index 1 ("2")
let removed = arr.splice(1, 1);
// add "2" back to position 1
arr.splice(1, 0, ...removed);
console.log(arr);
If you don't have access to ES6's spread operator, you could use .shift()
to get the first element out of removed
:
let arr = [1,2,3,4,5,6];
// remove 1 element from index 1 ("2")
let removed = arr.splice(1, 1);
// add "2" back to position 1
arr.splice(1, 0, removed.shift());
console.log(arr);
I'd be tempted to wrap your arrays in some kind of undoable utility. For example:
function undoable(value) {
let history = [value];
return {
value() {
return history[history.length - 1];
},
update(func) {
let copy = [...this.value()];
func(copy);
history.push(copy);
return copy;
},
undo() {
history.pop();
return this.value();
}
}
}
You could use this to handle undo behaviour.
let array = undoable([]);
array.update(arr => arr.push(2));
// [2]
array.update(arr => arr.push(3));
// [2, 3]
array.undo();
// [2]
You could make this even safer and more generic if you treat the values as immutable during the calls to update
. At that point you wouldn't need to defensively copy your array before passing it to func
. However, it would require you to use methods like filter
and slice
instead of splice
.
Clicking on the Delete random item
button will result in deletion of a random element from the arr
array. The deleted element is being stored inside the deleted
array.
Clicking on the Undo deletion
button will move the deleted element back into the arr
array, into the same position.
var arr = [5,1,2,6,4,8,0,7],
stored = arr.slice(),
deleted = [],
btn = document.getElementById('deleteBtn'),
undoBtn = document.getElementById('undoBtn');
btn.addEventListener('click', function(){
var randomElem = Math.floor(Math.random() * arr.length),
deleteElem = arr.splice(randomElem, 1);
deleted.push(...deleteElem);
console.log(arr);
console.log(deleteElem);
});
undoBtn.addEventListener('click', function(){
if (arr.length >= 0 && arr.length < stored.length){
var elem = deleted[deleted.length-1],
index = stored.indexOf(elem);
arr.splice(index, 0, elem);
deleted.pop();
console.log(arr);
}
});
console.log(arr);
<button id='deleteBtn'>Delete random item</button>
<button id='undoBtn'>Undo deletion</button>
If you only need one level of undo, you can just copy the array before deletion. If the user wants to "undo" then revert the array back to its previous incarnation.
var arr = [1,2,3,4,5,6];
var tempArr;
function removeThing(arr, index) {
tempArr = arr;
arr.splice(index, 1);
}
function undo() {
arr = tempArr;
}