vue-smooth-dnd icon indicating copy to clipboard operation
vue-smooth-dnd copied to clipboard

Initial Drag Operation does not take affect when using v-show

Open zherman91 opened this issue 4 years ago • 10 comments

I have found that when hiding the div that houses the drag containers using the v-show directive, the first initial drag operation does not take affect.

Do you know of a way around this that will still allow me to hide the containers until they are needed? Possibly a way to initialize the containers after they are shown like simulate a drag or something? Any help you can provide is greatly appreciated. Thanks.

Really nice library BTW. It's really helped me out a lot so thank you!

zherman91 avatar Sep 10 '19 19:09 zherman91

I am also facing the same can you please look into it and provide some solution or the workaround. Thanks.

rahulgupta-dev avatar Sep 23 '19 07:09 rahulgupta-dev

Good morning @rahulguptagithub

I actually found the issue i was facing and was able to correct it. I found that when hiding the dragging containers via v-show, it's almost as if they aren't fully rendered or 'ready' for the initial drag. So, what i did (which may not be correct) was apply a timeout of 300ms to the showing of the drag containers. In my situation, the drag containers were hidden within a card that expands to show you all the content. When the card expands, i simply wait to show the containers with that small delay which is unnoticeable and it works beautifully. Hopefully this makes sense. I'd be glad to help if you want to share your code and need assistance.

zherman91 avatar Sep 23 '19 14:09 zherman91

@zherman91

Thanks for replying.

Below is the code is given which get loaded on some click event, as per your suggestion I have added the delay when mounted but this seems not working out for me. Thanks.

<template>
  <display-panel @closed="closeDialog">
	<template slot="content">
	  <div>
		<div class="section-title">{{$t('edit_display_order')}}</div>
		<div class="divider branding-color" />
		<div
		  class="display-order-edit-info"
		></div>
		<div class="drag-drop-container">
		  <Container
			v-show="showDragContainer"
			ref="quickLinkDragDrop"
			@drop="onDrop"
			lock-axis="y"
			drag-class="drag-div"
			drop-class="drag-div"
			drag-handle-selector=".shelf-icon"
			:get-ghost-parent="getGhostParent"
		  >
			<Draggable v-for="(link,index) in items" :key="link.name">
			  <div class="drag-block">
				<div class="order-number">{{ index + 1 }}</div>
				<div class="content-block">
				  <div class="ellipsis">{{ link.name }}</div>
				  <small class="color-secondary ellipsis" style="width: 250px;">{{ link.url }}</small>
				</div>
				<div class="shelf-icon">
				  <i class="micon-handle-horizontal sort-icon"></i>
				</div>
			  </div>
			</Draggable>
		  </Container>
		</div>
	  </div>
	</template>
  </display-panel>
</template>	

<script>
	   
import { Container, Draggable } from 'vue-smooth-dnd'
export default {
  name: 'DragComponent',
  components: {
	Container,
	Draggable
  },
  props: {
	itemLinks: {
	  type: Array,
	  default: () => []
	}
  },
  mounted() {
	setTimeout(() => {
	  this.showDragContainer = true
	}, 3000)
  },
  data() {
	return {
	  isDragging: false,
	  items: [...this.itemLinks],
	  showDragContainer: false
	}
  },
  methods: {
	getGhostParent() {
	  return document.body
	},
	closeDialog() {
	  this.$emit('closed', this.items)
	},
	applyDrag(items, dragResult) {
	  const { removedIndex, addedIndex, payload } = dragResult
	  if (removedIndex === null && addedIndex === null) return items
	  const result = [...items]
	  let itemToAdd = payload

	  if (removedIndex !== null) {
		itemToAdd = result.splice(removedIndex, 1)[0]
	  }

	  if (addedIndex !== null) {
		result.splice(addedIndex, 0, itemToAdd)
	  }
	  return result
	},
	onDrop(dragResult) {
	  this.items = this.applyDrag(this.items, dragResult)
	}
  },
  watch: {
	items(items) {
	  this.isValid = this.items.some((link, index) => {
		return link.order_number !== index + 1
	  })
	}
  }
}
</script>

rahulgupta-dev avatar Sep 23 '19 14:09 rahulgupta-dev

I noticed that you have an @closed event on the main display-panel. When does this get shown? I would try having it show only the drag containers when you click a button to test the functionality. In other words, instead of showing the drag containers in the mounted call, try showing them when you click a button for testing. Does this make sense?

zherman91 avatar Sep 23 '19 14:09 zherman91

@zherman91 As I am using another parent component which is display-panel in which the container is included as the child component, hence I was using the mounted call to delay the container display, on click of a button we create the component called display-panel.

rahulgupta-dev avatar Sep 23 '19 16:09 rahulgupta-dev

Got it. What i would try is initializing the drag containers based off a watcher. For example, since the parent component will show the containers via 'showDragContainer', what if you made 'showDragContainer' a watch and added the delay to the building of the drag scene. I can't find in your code where it initializes the drag containers but that's what needs the delay not the actual showing of the containers. Sorry if that was confusing.

zherman91 avatar Sep 23 '19 16:09 zherman91

@zherman91 It would be helpful if you can paste your example code for the issue you have faced, and did not understand what you mean by initializing the container as I am directly importing it from the vue-smooth-dnd and using Thanks

rahulgupta-dev avatar Sep 23 '19 16:09 rahulgupta-dev

Ill see if i can put something together to help you out. Ill be in touch.

zherman91 avatar Sep 23 '19 20:09 zherman91

@zherman91 I meant to paste your problem code and the solution by that I may derive some solution thanks.

rahulgupta-dev avatar Sep 24 '19 11:09 rahulgupta-dev

@zherman91 It did work when I used v-if instead of using v-show for the container, Thanks for the help.

<Container
			v-if="showDragContainer"
			ref="quickLinkDragDrop"
			@drop="onDrop"
			lock-axis="y"
			drag-class="drag-div"
			drop-class="drag-div"
			drag-handle-selector=".shelf-icon"
			:get-ghost-parent="getGhostParent"
		  >
			<Draggable v-for="(link,index) in items" :key="link.name">
			  <div class="drag-block">
				<div class="order-number">{{ index + 1 }}</div>
				<div class="content-block">
				  <div class="ellipsis">{{ link.name }}</div>
				  <small class="color-secondary ellipsis" style="width: 250px;">{{ link.url }}</small>
				</div>
				<div class="shelf-icon">
				  <i class="micon-handle-horizontal sort-icon"></i>
				</div>
			  </div>
			</Draggable>
		  </Container>

rahulgupta-dev avatar Oct 01 '19 07:10 rahulgupta-dev