7032ed9a823dbb9358b4e463a5d3ea5f355e4e2dc2b3aafe515b8d9df184208bbf718d34380f65818ff4cec80eecbf1e09ac90d36bd2a3df63555b2ebafba7 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. <p align="center"><img width="140"src="https://raw.githubusercontent.com/SortableJS/Vue.Draggable/master/logo.svg?sanitize=true"></p>
  2. <h1 align="center">vue.draggable.next</h1>
  3. [![CircleCI](https://circleci.com/gh/SortableJS/vue.draggable.next.svg?style=shield)](https://circleci.com/gh/SortableJS/Vue.Draggable)
  4. [![Coverage](https://codecov.io/gh/SortableJS/vue.draggable.next/branch/master/graph/badge.svg)](https://codecov.io/gh/SortableJS/Vue.Draggable)
  5. [![codebeat badge](https://codebeat.co/badges/7a6c27c8-2d0b-47b9-af55-c2eea966e713)](https://codebeat.co/projects/github-com-sortablejs-vue-draggable-master)
  6. [![GitHub open issues](https://img.shields.io/github/issues/SortableJS/vue.draggable.next.svg)](https://github.com/SortableJS/Vue.Draggable/issues?q=is%3Aopen+is%3Aissue)
  7. [![npm download](https://img.shields.io/npm/dt/vuedraggable.svg?maxAge=30)](https://www.npmjs.com/package/vuedraggable)
  8. [![npm download per month](https://img.shields.io/npm/dm/vuedraggable.svg)](https://www.npmjs.com/package/vuedraggable)
  9. [![npm version](https://img.shields.io/npm/v/vuedraggable/next.svg)](https://www.npmjs.com/package/vuedraggable/v/next)
  10. [![MIT License](https://img.shields.io/github/license/SortableJS/vue.draggable.next.svg)](https://github.com/SortableJS/vue.draggable.next/blob/master/LICENSE)
  11. Vue component (Vue.js 3.0) allowing drag-and-drop and synchronization with view model array.
  12. For Vue 2 and Vue 1 version check: https://github.com/SortableJS/Vue.Draggable
  13. Based on and offering all features of [Sortable.js](https://github.com/RubaXa/Sortable)
  14. ## Demo
  15. ![demo gif](https://raw.githubusercontent.com/SortableJS/vue.draggable.next/master/example.gif)
  16. ## Live Demos
  17. https://sortablejs.github.io/vue.draggable.next/
  18. ## Features
  19. * Full support of [Sortable.js](https://github.com/RubaXa/Sortable) features:
  20. * Supports touch devices
  21. * Supports drag handles and selectable text
  22. * Smart auto-scrolling
  23. * Support drag and drop between different lists
  24. * No jQuery dependency
  25. * Keeps in sync HTML and view model list
  26. * Compatible with Vue.js 3.0 transition-group
  27. * Cancellation support
  28. * Events reporting any changes when full control is needed
  29. * Reuse existing UI library components (such as [vuetify](https://vuetifyjs.com), [element](http://element.eleme.io/), or [vue material](https://vuematerial.io) etc...) and make them draggable using `tag` and `componentData` props
  30. ## Donate
  31. Find this project useful? You can buy me a :coffee: or a :beer:
  32. [![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=GYAEKQZJ4FQT2&currency_code=USD&source=url)
  33. ## Installation
  34. ### With npm or yarn
  35. ```bash
  36. yarn add vuedraggable@next
  37. npm i -S vuedraggable@next
  38. ```
  39. ### with direct link
  40. ```html
  41. <script src="//cdnjs.cloudflare.com/ajax/libs/vue/3.0.2/vue.min.js"></script>
  42. <!-- CDNJS :: Sortable (https://cdnjs.com/) -->
  43. <script src="//cdn.jsdelivr.net/npm/sortablejs@1.10.2/Sortable.min.js"></script>
  44. <!-- CDNJS :: Vue.Draggable (https://cdnjs.com/) -->
  45. <script src="//cdnjs.cloudflare.com/ajax/libs/Vue.Draggable/4.0.0/vuedraggable.umd.min.js"></script>
  46. ```
  47. [cf example section](https://github.com/SortableJS/Vue.Draggable/tree/master/example)
  48. ## Typical use:
  49. ``` html
  50. <draggable
  51. v-model="myArray"
  52. group="people"
  53. @start="drag=true"
  54. @end="drag=false"
  55. item-key="id">
  56. <template #item="{element}">
  57. <div>{{element.name}}</div>
  58. </template>
  59. </draggable>
  60. ```
  61. ``` js
  62. import draggable from 'vuedraggable'
  63. ...
  64. export default {
  65. components: {
  66. draggable,
  67. },
  68. data() {
  69. return {
  70. drag: false,
  71. }
  72. },
  73. ...
  74. ```
  75. The `item` slot should be used to display items of the list. It receives the element value and the element index as slot-props.
  76. ### With `transition-group`:
  77. ``` html
  78. <draggable v-model="myArray" tag="transition-group" item-key="id">
  79. <template #item="{element}">
  80. <div> {{element.name}} </div>
  81. </template>
  82. </draggable>
  83. ```
  84. ### With footer slot:
  85. ``` html
  86. <draggable v-model="myArray" item-key="id">
  87. <template #item="{element}">
  88. <div> {{element.name}} </div>
  89. </template>
  90. <template #footer>
  91. <button @click="addPeople">Add</button>
  92. </template>
  93. </draggable>
  94. ```
  95. ### With header slot:
  96. ``` html
  97. <draggable v-model="myArray" item-key="id">
  98. <template #item="{element}">
  99. <div> {{element.name}} </div>
  100. </template>
  101. <template #header>
  102. <button @click="addPeople">Add</button>
  103. </template>
  104. </draggable>
  105. ```
  106. ### With Vuex:
  107. ```html
  108. <draggable v-model='myList'>
  109. ```
  110. ```javascript
  111. computed: {
  112. myList: {
  113. get() {
  114. return this.$store.state.myList
  115. },
  116. set(value) {
  117. this.$store.commit('updateList', value)
  118. }
  119. }
  120. }
  121. ```
  122. ### Migrate from vue 2 version:
  123. Breaking changes:
  124. 1) Use `item` slot instead of default to display elements
  125. 2) Provide a key for items using `itemKey` props
  126. From:
  127. ``` html
  128. <!-- vue 2 version -->
  129. <draggable v-model="myArray">
  130. <div v-for="element in myArray" :key="element.id">{{element.name}}</div>
  131. </draggable>
  132. ```
  133. To:
  134. ``` html
  135. <draggable v-model="myArray" item-key="id">
  136. <template #item="{element}">
  137. <div>{{element.name}}</div>
  138. </template>
  139. </draggable>
  140. ```
  141. Breaking changes:
  142. 3) When using transition, you should now use the `tag` props and `componentData` to create the transition
  143. From
  144. ``` html
  145. <!-- vue 2 version -->
  146. <draggable v-model="myArray">
  147. <transition-group name="fade">
  148. <div v-for="element in myArray" :key="element.id">
  149. {{element.name}}
  150. </div>
  151. </transition-group>
  152. </draggable>
  153. ```
  154. to
  155. ``` html
  156. <draggable v-model="myArray" tag="transition-group" :component-data="{name:'fade'}">
  157. <template #item="{element}">
  158. <div>{{element.name}}</div>
  159. </template>
  160. </draggable>
  161. ```
  162. ### Props
  163. #### modelValue
  164. Type: `Array`<br>
  165. Required: `false`<br>
  166. Default: `null`
  167. Input array to draggable component. Typically same array as referenced by inner element v-for directive.<br>
  168. This is the preferred way to use Vue.draggable as it is compatible with Vuex.<br>
  169. It should not be used directly but only though the `v-model` directive:
  170. ```html
  171. <draggable v-model="myArray">
  172. ```
  173. #### list
  174. Type: `Array`<br>
  175. Required: `false`<br>
  176. Default: `null`
  177. Alternative to the `modelValue` prop, list is an array to be synchronized with drag-and-drop.<br>
  178. The main difference is that `list` prop is updated by draggable component using splice method, whereas `modelValue` is immutable.<br>
  179. **Do not use in conjunction with modelValue prop.**
  180. #### itemKey
  181. Type: `String` or `Function`<br>
  182. Required: `true`<br>
  183. The property to be used as the element key. Alternatively a function receiving an element of the list and returning its key.
  184. #### All sortable options
  185. Sortable options can be set directly as vue.draggable props since version 2.19.
  186. This means that all [sortable option](https://github.com/RubaXa/Sortable#options) are valid sortable props with the notable exception of all the method starting by "on" as draggable component expose the same API via events.
  187. kebab-case property are supported: for example `ghost-class` props will be converted to `ghostClass` sortable option.
  188. Example setting handle, sortable and a group option:
  189. ```HTML
  190. <draggable
  191. v-model="list"
  192. handle=".handle"
  193. :group="{ name: 'people', pull: 'clone', put: false }"
  194. ghost-class="ghost"
  195. :sort="false"
  196. @change="log"
  197. >
  198. <!-- -->
  199. </draggable>
  200. ```
  201. #### tag
  202. Type: `String`<br>
  203. Default: `'div'`
  204. HTML node type of the element that draggable component create as outer element for the included slot.<br>
  205. It is also possible to pass the name of vue component as element. In this case, draggable attribute will be passed to the create component.<br>
  206. See also [componentData](#componentdata) if you need to set props or event to the created component.
  207. #### clone
  208. Type: `Function`<br>
  209. Required: `false`<br>
  210. Default: `(original) => { return original;}`<br>
  211. Function called on the source component to clone element when clone option is true. The unique argument is the viewModel element to be cloned and the returned value is its cloned version.<br>
  212. By default vue.draggable reuses the viewModel element, so you have to use this hook if you want to clone or deep clone it.
  213. #### move
  214. Type: `Function`<br>
  215. Required: `false`<br>
  216. Default: `null`<br>
  217. If not null this function will be called in a similar way as [Sortable onMove callback](https://github.com/RubaXa/Sortable#move-event-object).
  218. Returning false will cancel the drag operation.
  219. ```javascript
  220. function onMoveCallback(evt, originalEvent){
  221. ...
  222. // return false; — for cancel
  223. }
  224. ```
  225. evt object has same property as [Sortable onMove event](https://github.com/RubaXa/Sortable#move-event-object), and 3 additional properties:
  226. - `draggedContext`: context linked to dragged element
  227. - `index`: dragged element index
  228. - `element`: dragged element underlying view model element
  229. - `futureIndex`: potential index of the dragged element if the drop operation is accepted
  230. - `relatedContext`: context linked to current drag operation
  231. - `index`: target element index
  232. - `element`: target element view model element
  233. - `list`: target list
  234. - `component`: target VueComponent
  235. HTML:
  236. ```HTML
  237. <draggable :list="list" :move="checkMove">
  238. ```
  239. javascript:
  240. ```javascript
  241. checkMove: function(evt){
  242. return (evt.draggedContext.element.name!=='apple');
  243. }
  244. ```
  245. See complete example: [Cancel.html](https://github.com/SortableJS/Vue.Draggable/blob/master/examples/Cancel.html), [cancel.js](https://github.com/SortableJS/Vue.Draggable/blob/master/examples/script/cancel.js)
  246. #### componentData
  247. Type: `Object`<br>
  248. Required: `false`<br>
  249. Default: `null`<br>
  250. This props is used to pass additional information to child component declared by [tag props](#tag).<br>
  251. Value: an object corresponding to the attributes, props and events we would pass to the component.
  252. Example (using [element UI library](http://element.eleme.io/#/en-US)):
  253. ```HTML
  254. <draggable tag="el-collapse" :list="list" :component-data="getComponentData()" item-key="name">
  255. <template #item="{element}">
  256. <el-collapse-item :title="element.title" :name="element.name">
  257. <div>{{element.description}}</div>
  258. </el-collapse-item>
  259. </template>
  260. </draggable>
  261. ```
  262. ```javascript
  263. methods: {
  264. handleChange() {
  265. console.log('changed');
  266. },
  267. inputChanged(value) {
  268. this.activeNames = value;
  269. },
  270. getComponentData() {
  271. return {
  272. onChange: this.handleChange,
  273. onInput: this.inputChanged,
  274. wrap: true,
  275. value: this.activeNames
  276. };
  277. }
  278. }
  279. ```
  280. ### Events
  281. * Support for Sortable events:
  282. `start`, `add`, `remove`, `update`, `end`, `choose`, `unchoose`, `sort`, `filter`, `clone`<br>
  283. Events are called whenever onStart, onAdd, onRemove, onUpdate, onEnd, onChoose, onUnchoose, onSort, onClone are fired by Sortable.js with the same argument.<br>
  284. [See here for reference](https://github.com/RubaXa/Sortable#event-object-demo)
  285. Note that SortableJS OnMove callback is mapped with the [move prop](https://github.com/SortableJS/Vue.Draggable/blob/master/README.md#move)
  286. HTML:
  287. ```HTML
  288. <draggable :list="list" @end="onEnd">
  289. ```
  290. * change event
  291. `change` event is triggered when list prop is not null and the corresponding array is altered due to drag-and-drop operation.<br>
  292. This event is called with one argument containing one of the following properties:
  293. - `added`: contains information of an element added to the array
  294. - `newIndex`: the index of the added element
  295. - `element`: the added element
  296. - `removed`: contains information of an element removed from to the array
  297. - `oldIndex`: the index of the element before remove
  298. - `element`: the removed element
  299. - `moved`: contains information of an element moved within the array
  300. - `newIndex`: the current index of the moved element
  301. - `oldIndex`: the old index of the moved element
  302. - `element`: the moved element
  303. ### Slots
  304. #### item
  305. The `item` slot is used to display one element of the list. Vue.draggable will iterate the list and call this slot for each element.
  306. Slot props:
  307. - `element` the element in the list
  308. - `index` the element index
  309. It is the only required slot.
  310. ```html
  311. <draggable v-model="myArray" item-key="id">
  312. <template #item="{element, index}">
  313. <div> {{index}} - {{element.name}} </div>
  314. </template>
  315. </draggable>
  316. ```
  317. #### Header
  318. Use the `header` slot to add none-draggable element inside the vuedraggable component.
  319. Ex:
  320. ``` html
  321. <draggable v-model="myArray" item-key="id">
  322. <template #item="{element}">
  323. <div> {{element.name}} </div>
  324. </template>
  325. <template #header>
  326. <button @click="addPeople">Add</button>
  327. </template>
  328. </draggable>
  329. ```
  330. #### Footer
  331. Use the `footer` slot to add none-draggable element inside the vuedraggable component.
  332. Ex:
  333. ``` html
  334. <draggable v-model="myArray" item-key="id">
  335. <template #item="{element}">
  336. <div> {{element.name}} </div>
  337. </template>
  338. <template #footer>
  339. <button @click="addPeople">Add</button>
  340. </template>
  341. </draggable>
  342. ```
  343. ### Example
  344. * [Clone](https://sortablejs.github.io/vue.draggable.next/#/custom-clone)
  345. * [Handle](https://sortablejs.github.io/vue.draggable.next/#/handle)
  346. * [Transition](https://sortablejs.github.io/vue.draggable.next/#/transition-example-2)
  347. * [Nested](https://sortablejs.github.io/vue.draggable.next/#/nested-example)
  348. * [Table](https://sortablejs.github.io/vue.draggable.next/#/table-example)