Skip to content
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

Implementing Restricted Column Movement for Specific Items #95

Open
OliverArthur opened this issue Jan 22, 2024 · 3 comments
Open

Implementing Restricted Column Movement for Specific Items #95

OliverArthur opened this issue Jan 22, 2024 · 3 comments

Comments

@OliverArthur
Copy link

Hello,

I'm currently working with a Vue component to create a draggable list across multiple columns. My objective is to restrict the movement of certain items between columns based on a specific property (e.g., required property).

In my implementation, items are draggable within and across columns. However, I need to implement a functionality where items marked as required should not be moved to other columns, but can still be rearranged within their own column.

Here is a snippet of my current implementation:

sortable-list.vue

<template>
	<div class="sortable">
		<div v-for="(column, index) in columns" :key="index" class="sortable__list">
			<div class="sortable__list-header">
				<strong :id="`column-header-${index}`">{{ column.name }}</strong>
			</div>
			<vue-draggable
				v-model="column.items"
				:group="groupName || 'default'"
				role="list"
				class="sortable__list-content"
				:direction="dragDirection"
				@move="onMove"
				@end="onEnd"
				@start="onStart"
			>
				<div
					v-for="item in column.items"
					:id="item.id"
					:key="item.id"
					:aria-grabbed="isGrabbed"
					class="sortable__list-item"
					role="listitem"
					tabindex="0"
				>
					<i class="c-sortable__list-item__icon" />
					{{ item.name }}
					<span v-if="item.required" class="sortable__list-item__required">required</span>
				</div>
			</vue-draggable>
		</div>
	</div>
</template>

<script lang="ts" setup>
	import { ref, computed } from "vue";
	import { VueDraggable } from "vue-draggable-plus";
	import { type SortableEvent, MoveEvent } from "sortablejs";
	import { SortableColumn, SortableItem } from "@/components/common/sortable-list/types";

	type AllowDropEffect = "move" | "none";

	interface Props {
		columns: SortableColumn[];
		groupName?: string;
	}

	const props = defineProps < Props > ();

	const isGrabbed = ref < boolean > (false);
	const dropEffect = ref < AllowDropEffect > ("none");

	// properties for handle drag direction
	const sortableItem = ref < SortableItem | null > (null);
	const dragDirection = computed(() => (sortableItem.value?.required ? "vertical" : "auto"));

	const emits = defineEmits < {
	(event: "on-start", evt: SortableEvent): void;
	(event: "on-end", evt: SortableEvent): void;
	(event: "on-move", evt: MoveEvent): void;
}> ();

	const onStart = (evt: SortableEvent) => {
		isGrabbed.value = true;
		dropEffect.value = "move";

		const grabbedItemId = evt.item.id;
		const grabbedItem = findDraggedItem(grabbedItemId);

		sortableItem.value = grabbedItem;
		emits("on-start", evt);
	};

	const onEnd = (evt: SortableEvent) => {
		if (evt.type === "end") {
			isGrabbed.value = false;
			dropEffect.value = "none";
			sortableItem.value = null;
		}
		emits("on-end", evt);
	};

	const onMove = (evt: MoveEvent) => {
		if (dragDirection.value === "vertical") {
			if (evt.from !== evt.to) {
				return false;
			}
		}
		emits("on-move", evt);
	};

	const findDraggedItem = (itemId: string) => {
		for (let column of props.columns) {
			// find the item with the matching id
			for (let item of column.items) {
				if (item.id === itemId) {
					return item;
				}
			}
		}
		return null;
	};
</script>

sortable-list-two-column.vue

<template>
	<div>
		<sortable-list class="sortable" :columns="columns" group="myGroup" />
	</div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
import sortableList from "@/components/common/sortable-list/sortable-list.vue";
import type { SortableColumn } from "@/components/common/sortable-list/types";

const columns = ref<SortableColumn[]>([
	{
		name: "Column 1",
		items: [
			{ id: "1", name: "Item 1" },
			{ id: "2", name: "Item 2" },
			{ id: "3", name: "Item 3" }
		]
	},
	{
		name: "Column 2",
		items: [
			{ id: "4", name: "Item 4" },
			{ id: "5", name: "Item 5" },
			{ id: "6", name: "Item 6", required: true }
		]
	}
]);
</script>

I have attempted to address this issue by making adjustments in the onStart and onMove events, as shown in the provided code. My approach involves controlling the draggable behavior based on the required property of the items. However, these modifications have not been successful

@gedrick
Copy link

gedrick commented Mar 4, 2024

Hi there @OliverArthur , any luck with this? I've been trying to prevent dragging a group into another group via the @Move handler and returning false doesn't seem to prevent the move at all.

@OliverArthur
Copy link
Author

Hi @gedrick ,

I gave up in the end after many different tries, and I think this library is not being maintained.

Now I'm using this library @formkit/drag-and-drop, which I discovered recently during Vue.js Amsterdam last week. It's a very good library and allows you to extend the drag-and-drop functionality via custom plugins that you can create.

@gedrick
Copy link

gedrick commented Mar 11, 2024

Hi @gedrick ,

I gave up in the end after many different tries, and I think this library is not being maintained.

Now I'm using this library @formkit/drag-and-drop, which I discovered recently during Vue.js Amsterdam last week. It's a very good library and allows you to extend the drag-and-drop functionality via custom plugins that you can create.

Thanks for the reply - I did ultimately get it working - I had to call .pause() on the draggable instance - but it was certainly more painful than I expected. And now dealing with what appears to be an abandoned library is very disheartening.

I will check out that one you linked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants