-
-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Document how to use with Vue.js #178
Comments
Hi @danielxvu yes that would be awesome! Unfortunately I have absolutely no knowledge of Vue myself. If you’re familiar with it would be great if you could help out here 🥂 |
This is a very rudimentary Vue composable I threw together in Typescript (barely) that's generally working for a project I'm working on. Bear in mind I'm just learning Vue, so I'll be very happy to take feedback and constructive criticism. Essentially, it creates a new DragSelect instance, provided an array of selectables and a selectable area. It tries to handle allowing for If Vue reactive objects get passed in, it should also set up watchers to update the DragSelect instance when they're updated. This is mostly to alleviate issues with template refs getting called before they're available in the template. There's probably a better way to handle this, but it works for now. I'll try to keep this updated as I find issues/improvements. /edit: Also, this is a really basic solution. It would probably be beneficial to return an object with the DS instance so that the various DragSelect methods are exposed. This was just an easy way to get it up and running for my needs. import { unref, isRef, ref, onMounted, onUnmounted, watchEffect } from 'vue'
import DragSelect from 'dragselect'
export function useDragSelect (selectables, area) {
// state encapsulated and managed by the composable
const selected = ref([])
let dragSelectInstance: DragSelect
function initDragSelect () {
// This is all doing some checking/cleanup to allow for different types of input
// selectables is always an array, but it can be an array of HTML elements,
// a vue ref() of HTML elements, or an array of Vue components
// Similarly, area can be either an HTML element or Vue component, ref() or not
if (unref(selectables) && unref(area)) {
const selectableElementArray = unref(selectables).map(el => {
if (el.__isVue) {
return el.$el
} else {
return unref(el)
}
})
let areaElement
if (unref(area).__isVue) {
areaElement = unref(area).$el
} else {
areaElement = unref(area)
}
if (dragSelectInstance instanceof DragSelect) {
dragSelectInstance.stop()
dragSelectInstance.setSettings({
selectables: selectableElementArray,
area: areaElement,
draggability: false
})
dragSelectInstance.start()
} else {
dragSelectInstance = new DragSelect({
selectables: selectableElementArray,
area: areaElement,
draggability: false
})
}
}
}
// if reactive objects like ref() have been passed in, use watchEffect
// to watch and rerun the dragSelect init if they change
if (isRef(selectables) || isRef(area)) {
watchEffect(initDragSelect)
}
function refreshSelected () {
if (dragSelectInstance) {
const dsSelection = dragSelectInstance.getSelection()
selected.value = dsSelection
}
}
// a composable can also hook into its owner component's
// lifecycle to setup and teardown side effects.
onMounted(() => {
initDragSelect()
if (dragSelectInstance) {
dragSelectInstance.subscribe('callback', (callbackObject) => {
refreshSelected()
})
}
})
onUnmounted(() => {
if (dragSelectInstance) dragSelectInstance.stop()
})
// expose managed state as return value
return selected
} |
I've made some updates that were helpful in my use. Mostly, returning more than just the list of selected elements, updating the selected elements on import { unref, isRef, ref, onMounted, onUnmounted, watchEffect } from 'vue';
import { unrefElement } from '@vueuse/core';
import DragSelect from 'dragselect';
export function useDragSelect(selectables, area) {
// state encapsulated and managed by the composable
const selected = ref([]);
let dragSelectInstance: DragSelect;
function initDragSelect() {
// This is all doing some checking/cleanup to allow for different types of input
// selectables is always an array, but it can be an array of HTML elements,
// a vue ref() of HTML elements, or an array of Vue components
// Similarly, area can be either an HTML element or Vue component, ref() or not
if (unref(selectables) && unref(area)) {
const selectableElementArray = unref(selectables).map((el) => {
return unrefElement(el);
});
const areaElement = unrefElement(area);
if (dragSelectInstance instanceof DragSelect) {
dragSelectInstance.stop();
dragSelectInstance.setSettings({
area: areaElement,
draggability: false,
});
dragSelectInstance.removeSelectables(
dragSelectInstance.getSelectables(),
true,
true
);
dragSelectInstance.addSelectables(selectableElementArray);
dragSelectInstance.start();
} else {
dragSelectInstance = new DragSelect({
area: areaElement,
selectables: selectableElementArray,
draggability: false,
});
dragSelectInstance.subscribe('dragmove', () => {
refreshSelected();
});
}
}
}
// if reactive objects like ref() have been passed in, use watchEffect
// to watch and rerun the dragSelect init if they change
if (isRef(selectables) || isRef(area)) {
watchEffect(initDragSelect);
}
function getInstance() {
return dragSelectInstance;
}
function clearSelected() {
dragSelectInstance.clearSelection(true);
}
function refreshSelected() {
if (dragSelectInstance) {
const dsSelection = dragSelectInstance.getSelection();
selected.value = dsSelection;
}
}
// a composable can also hook into its owner component's
// lifecycle to setup and teardown side effects.
onMounted(() => {
initDragSelect();
});
onUnmounted(() => {
if (dragSelectInstance) dragSelectInstance.stop();
});
// return composable's managed state as return value
return { selected, clearSelected, instance: getInstance() };
} |
Is your feature request related to a problem? Please describe.
Official documentation for usage with Vue.js projects is lacking.
Describe the solution you'd like
A guided example on par with the one for React.
Describe alternatives you've considered
I would be happy to contribute a pull request if you are open to reviewing and accepting it.
Additional context
Providing examples of composables based on this library would be ideal, similar to how the React guided example documents how to use this library with useEffect.
The text was updated successfully, but these errors were encountered: