Open akorajac opened 3 years ago
I'm also interested by using index has key. Normally I use this way in a v-for :
<div
v-for="(element, key) in elements"
:key="`element${key}`"
>
{{ element }}
</div>
it doesn't seem possible the default should be set to index automatically tbh..
I did it this way:
<draggable
v-model="myArray"
:item-key="((item) => myArray.indexOf(item))"
...
>
<!-- ... -->
</draggable>
Not beautiful but works fine.
EDIT: Will only work if your array elements are unique. (Two objects with the same content are also unique when they are two different instances.)
i've run into same issue... am a bit puzzled by the most simple case of plain array with no props not being covered :(
Another solution is to wrap the array in a computed property and add an id
computed: {
myArrayWithId() {
return this.myArray.map((item, index) => {
item.id = index
return item
})
}
}
Another solution is to wrap the array in a computed property and add an id
The problem is that the id changes when dragging the elements around. It may be better to clone the array and assign the IDs only once. Then watch the cloned array for changes (adding or removing elements) and write those changes without the ID back into the original array.
Good point. Maybe the ID could be based on some intrinsic property rather than the array index, for example, a JSON string of the object?
computed: {
myArrayWithId() {
return this.myArray.map(item => {
item.id = JSON.stringify(item)
return item
})
}
}
Chiming in here that I would also like the ability to do this without having the clone the array
+1
without having the clone the array
Short answer: not possible
Long answer: Why does sortable need unique values?
Imagine you have a sortable list with a title and a description. The description can be toggled. Looks like this:
When we swap B and C, we would expect to get this result:
But instead we get this:
This happens because we are using the index as the key element. Vue.js only knows that the we toggled the third element of our array but as we swapped B and C, B is now our third element. Therefore we need to have unique elements inside our array.
Doesn't this just depend on the data structure of the elements and what is keeping track of the visibility? If your data were:
const list = [
{ title: 'A', description: 'descA', visible: false },
{ title: 'B', description: 'descB', visible: false },
{ title: 'C', description: 'descC', visible: true },
]
Then re-ordering the elements would preserve the visibility. If you were keeping track of the visibility states in a second list, then sure, re-ordering would screw that up. Though it seems like it would be nicer in the template to use the object properties rather than lookup in a list:
<div v-if="element.visible"></div>
vs
<div v-if="index in visibleIndices"></div>
or if you were tracking IDs
<div v-if="element.id in visibleIds"></div>
It just seems like KaliaJS's v-for
usage of key
is pretty common pattern that would be appropriate here (and works in the Vue 2 version of this library).
@MikesAtMIT When you store all data inside the array and don't rely on the internal component variables, it doesn't matter what type of key you use.
It should even work without the visible property by using the object index as the key and an internal variable of the foldable component (:item-key="((item) => list.indexOf(item))"
). The objects in your example list are all unique (no reference).
I was facing the issue where the internal component variables haven't swapped with the elements inside the array and could solve it by using the item key above without the need of adding an id property.
Yeah, the function for the key should work in my actual use case, so thanks for the suggestion. Still, seems like a weird workaround for essentially just using the index as the key like you could in a v-for
.
What I terrible idea to iterate own way instead of letting user write his own code. Why just not to keep this how it was done in Vue 3, looks like not only Vue 3 designed to break everything, now every 3rd party lib is also breaking everything and making stupid changes.
when you drag an item, you can add a unique id into the clone item like this, then you can use the id as item-key:
// data source
<draggable :clone="onClone">
...
</draggable>
const onClone = (item) => {
return {
...item,
id: uuidv4(),
};
};
// put area
<draggable item-key="id">
...
</draggable>
https://github.com/SortableJS/vue.draggable.next/blob/master/example/components/clone.vue
How could I pass the index in the
itemKey
prop instead of a value from the object. In my case in want to allow duplicates inside the array that the items are being dropped to.