-
-
Save jbwl/f344a9769a87aa4732b5d833f29f9eaa to your computer and use it in GitHub Desktop.
Apply Drag and Drop to QTable rows using SortableJs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Taken from https://github.com/angular/components/blob/master/src/cdk/drag-drop/drag-utils.ts | |
/** | |
* @license | |
* Copyright Google LLC All Rights Reserved. | |
* | |
* Use of this source code is governed by an MIT-style license that can be | |
* found in the LICENSE file at https://angular.io/license | |
*/ | |
/** Clamps a number between zero and a maximum. */ | |
function clamp(value: number, max: number): number { | |
return Math.max(0, Math.min(max, value)); | |
} | |
/** | |
* Moves an item one index in an array to another. | |
* @param array Array in which to move the item. | |
* @param fromIndex Starting index of the item. | |
* @param toIndex Index to which the item should be moved. | |
*/ | |
export function moveItemInArray<T = unknown>( | |
array: T[], | |
fromIndex: number, | |
toIndex: number | |
): void { | |
const from = clamp(fromIndex, array.length - 1); | |
const to = clamp(toIndex, array.length - 1); | |
if (from === to) { | |
return; | |
} | |
const target = array[from]; | |
const delta = to < from ? -1 : 1; | |
for (let i = from; i !== to; i += delta) { | |
array[i] = array[i + delta]; | |
} | |
array[to] = target; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<q-table :rows="rows" :columns="columns" row-key="name"> | |
<template #body-cell-drag-handle="props"> | |
<q-td :props="props"> | |
<q-icon name="drag_handle" class="drag-handle" /> | |
</q-td> | |
</template> | |
</q-table> | |
</template> | |
<script lang="ts"> | |
import Sortable from 'sortablejs'; | |
import { | |
defineComponent, | |
ref, | |
getCurrentInstance, | |
onMounted, | |
onUnmounted, | |
} from 'vue'; | |
import { moveItemInArray } from './move'; | |
const columns = [ | |
{ | |
name: 'drag-handle', | |
align: 'left', | |
}, | |
{ | |
name: 'name', | |
align: 'left', | |
label: 'Name', | |
field: 'name', | |
}, | |
]; | |
export default defineComponent({ | |
name: 'QTableDndShowcase', | |
setup() { | |
const rows = ref([ | |
{ name: 'Frozen Yogurt' }, | |
{ name: 'Ice cream sandwich' }, | |
{ name: 'Eclair' }, | |
]); | |
let sortable: Sortable; | |
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | |
const instance = getCurrentInstance()!.proxy!; | |
onMounted(() => { | |
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | |
const tableBody = ( | |
instance.$el as HTMLElement | |
).querySelector<HTMLElement>('.q-table > tbody')!; | |
// Check out other options at https://github.com/SortableJS/Sortable#options | |
sortable = Sortable.create(tableBody, { | |
handle: '.drag-handle', | |
animation: 150, | |
onUpdate({ oldIndex, newIndex }) { | |
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion | |
moveItemInArray(rows.value, oldIndex!, newIndex!); | |
}, | |
}); | |
}); | |
onUnmounted(() => { | |
sortable.destroy(); | |
}); | |
return { | |
columns, | |
rows, | |
}; | |
}, | |
}); | |
</script> | |
<style lang="scss" scoped> | |
.drag-handle { | |
cursor: move; | |
// stylelint-disable-next-line value-no-vendor-prefix | |
cursor: -webkit-grabbing; | |
} | |
</style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment