-
-
Save royteusink/ecae35628d609e8a6572789877bbf1b8 to your computer and use it in GitHub Desktop.
if (action.toindex < 0) return state; | |
var olditem = state.get(action.index); | |
var newlist = state.delete(action.index).insert(action.toindex, olditem); | |
return newlist; |
Be careful – this code will change behavior depending on whether you're moving an item up or down in the list. When moving an item to a lower index, it will appear before the item previously at the target index. When moving an item to a higher index,
it will appear after the item previously at the target index.
To avoid this you can do the following:
if (action.toIndex < 0) return state;
const sourceItem = state.get(action.index);
const targetItem = state.get(action.toIndex);
state = state.delete(action.index);
const targetIndex = state.indexOf(targetItem);
return state.insert(targetIndex, sourceItem);
If the list is huge, you may want to just compute whether to alter the insertion index based on if action.index < action.toIndex
for performance reasons.
BTW, how can I move item inside of nested list?
For example:
move item with id 2
in path [2, 1]
const list = [
{ id: 1 },
{ id: 2 },
{ id: 3, children: [{ id: 5 }, { id: 6 }] },
{ id: 4 },
]
Don't know what i had copied wrong, but also #comment-2271960 didn't worked for me with v4 immutable.
This is what i now got, also in the need to move items in nested map/array a lot:
import { List, Map } from "immutable";
/**
* Move item inside a list to new index
* @param {List} value
* @param {int} oldI
* @param {int} newI
* @return {List}
*/
const moveItem = (value, oldI, newI) => {
if (!value || 0 > newI || value.size < newI) return value;
const srcItem = value.get(oldI);
return value.splice(oldI, 1).splice(newI, 0, srcItem);
};
/**
* Moves an item in a list which is in a Map/OrderedMap
*
* @param {Map|OrderedMap} state
* @param {List} stateKeys
* @param {int} go if positive will move the number further e.g.: `2` positions further: old is 1, new is 3, go is `2`; when negative will move back: old is 3, new is 1, go is `-2`
* @return {*}
*/
const stateMoveItem = (state, stateKeys, go) => {
const valueStateKeys = stateKeys.slice(0, -1);
const index = stateKeys.slice(-1).get(0);
return state.setIn(
valueStateKeys,
moveItem(state.getIn(valueStateKeys), index, index + go)
);
};
const state = List([
Map({ id: 1 }),
Map({ id: 2 }),
Map({
id: 3,
children: List([Map({ id: 5 }), Map({ id: 6 }), Map({ id: 7 })])
}),
Map({ id: 4 })
]);
let movedFirstLevel1 = moveItem(state, 0, 1); // switch `id:1` and `id:2`
console.log(movedFirstLevel1.toJS());
let movedFirstLevel2 = moveItem(state, 1, 2); // move `id:2` BEFORE `id:4`
console.log(movedFirstLevel2.toJS());
let movedChildren1 = stateMoveItem(state, List([2, "children", 1]), 1); // move `id:6` AFTER `id:7`
console.log(movedChildren1.toJS());
let movedChildren2 = stateMoveItem(state, List([2, "children", 2]), -1); // move `id:7` before `id:6`
console.log(movedChildren2.toJS());
let movedChildren3 = stateMoveItem(state, List([2, "children", 2]), -2); // move `id:7` before `id:5`
console.log(movedChildren3.toJS());
// `go` is not `newIndex`, when using `newIndex`, substract `oldIndex` from `newIndex` and you got `go`
const oldIndex = 1;
const newIndex = 2;
let movedChildren4 = stateMoveItem(state, List([2, "children", oldIndex]), newIndex - oldIndex); // move `id:6` AFTER `id:7`
console.log(movedChildren4.toJS());
thanks!