Coder Social home page Coder Social logo

rhwilr / vue-nestable Goto Github PK

View Code? Open in Web Editor NEW
318.0 10.0 63.0 1.77 MB

A simple drag & drop hierarchical list made as a vue component.

Home Page: https://rhwilr.github.io/vue-nestable/

License: MIT License

JavaScript 28.25% Vue 61.76% CSS 7.72% HTML 1.59% TypeScript 0.69%
vue vue-components vue-nestable drag

vue-nestable's Introduction

vue-nestable

Drag & drop hierarchical list made as a vue component.

NPM Version Build Status

This package is currently only compatible with Vue 2. Vue 3 compatibility may be added in the future, though there are currently no plans for it.


Goals

  • A simple vue component to create a draggable list to customizable items
  • Reorder items by dragging them above another item
  • Intuitively nest items by dragging right
  • Fully customizable, ships with no CSS
  • Everything is configurable: item identifier, max nesting level, threshold for nesting

Table of contents

Demo

Live Demo

Installation

Install the plugin:

npm install --save vue-nestable

Use the plugin in your app:

import Vue from 'vue'
import VueNestable from 'vue-nestable'

Vue.use(VueNestable)

You can also import the components on-demand, if you wish to do so:

import { VueNestable, VueNestableHandle } from 'vue-nestable'

export default {
  components: {
    VueNestable,
    VueNestableHandle
  }
  ...
}

Example

You only need two components: vue-nestable which renders the list and vue-nestable-handle which indicates the area the user can drag the item by.

Important Note: Each item must have a unique id property and it must be a valid css class name. It can not contain a :, ,, ., ; or other special characters that are invalid in a css class name.

<template>

  <vue-nestable v-model="nestableItems">
    <vue-nestable-handle
      slot-scope="{ item }"
      :item="item">
      {{ item.text }}
    </vue-nestable-handle>
  </vue-nestable>

</template>

<script type="text/babel">
export default {
  data () {
    return {
      nestableItems: [
        {
          id: 0,
          text: 'Andy'
        }, {
          id: 1,
          text: 'Harry',
          children: [{
            id: 2,
            text: 'David'
          }]
        }, {
          id: 3,
          text: 'Lisa'
        }
      ]
    }
  }
}
</script>

Styling

By default, vue-nestable comes without any styling. Which means you can customize the appearance completely to your needs. However, if you want you can take a look at the style used in the demo: example/assets/vue-nestable.css

Props

The following props can be passed to the <VueNestable> Component:

Property Type Default Description
value Array [ ] Array of objects to be used in the list. Important: Each item must have a unique key by which it can be identified. By default the key is assumed to be named id but you can change it by setting the keyProp property.
threshold Number 30 Amount of pixels by which the mouse must be move horizontally before increasing/decreasing level (nesting) of current element.
maxDepth Number 10 Maximum available level of nesting. Setting this to 0 will prevent dragging altogether.
group String or Number random String Different group numbers may be passed if you have more than one nestable component on a page and want some extra styles for portal instances.
keyProp String (Optional) 'id' Name of the property that uniquely identifies an item.
childrenProp String (Optional) 'children' Name of the property that holds an array of children.
class String (Optional) null Name of the property for classes to add to the item.
hooks Object (Optional) {} Allows you to register hooks that fire whenever vue-nestable performs some action
rtl Boolean (Optional) false Add rtl support to vue-nestable

Slots

The <VueNestable> Component has two slots that can be used to render items and a placeholder. See Example for an example on how to use them.

Slot Name Props Description
default item, index, isChild This slot is used to render the items in the list, use the scoped-slot property item to render the element.
placeholder Lets you define a custom template that is used when no elements are in the list

Events

Events are triggered when an item was moved or when a drag operation was completed. When you use v-model to bind your data, the @input event will automatically be handled.

Event Parameters Description
input value triggered whenever the list changes
change value, options triggered when the user dropped the item. options is passed as the second parameter in the event and contains the following properties: { items, pathTo }

Hooks

Hooks allow you to get finer controll over which items can be moved or take action when a specific item is moved.

Hooks are passed as an Object to the :hooks prop. The object defines a key with the hook name and a function that will be called when the hook fires.

{
  'beforeMove': this.myHookFunction
}

Look here of an example on how to prevent one item from being moved.

Hook Name Parameters Description
beforeMove { dragItem, pathFrom, pathTo } Fires when an item is about to be moved. Returning false will cancel that action.

vue-nestable's People

Contributors

core-entin avatar dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar iceflash avatar ilkome avatar originalroohi avatar passi246 avatar pbastowski avatar punpunm avatar rhwilr avatar vavrecan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vue-nestable's Issues

Copy element when pressed CTRL

Hello,

It would be interesting to have the option to active the ability to copy the element when the key CTRL is pressed before start dragging

If you find it pertinent, here it is an request

Thank you!

Emit mouseenter event

Hello. In my tree, I have an opportunity to hide and to open some part of tree.
I haven't opportunity to open a hidden node on move other tree node.

Please add emit @mouseenter event for VueNestable component for it.

For example (video) https://yadi.sk/i/74FfrnOdwvIlcA

Change ghost image when using multiple VueNestable components with same group

I am creating a page with at least 2 VueNestable components and allowing items to be moved between lists. When I drag an item, the ghost will not only include the item from the original list but the same item from each of the other components. The movements all work correctly but the ghost shows this extra visible effects that are confusing. If I can modify that image, I would be in great shape. Any assistance would be greatly appreciated. Thanks!

How to get the index of array?

<template>

<vue-nestable
    v-model="nestableItems"
    :max-depth="1">
    <template slot-scope="{ item }">
        <div class="row mt-2">
            <div class="col-md-1">
                <vue-nestable-handle :item="item">
                    <div class="block-handle"></div>
                </vue-nestable-handle>
            </div>
            <div class="col-md-1">
                <button class="btn btn-danger" @click="removeColumn(index)"> <!-- How to get index? -->
                    <i class="fas fa-trash"></i>
                </button>
            </div>
        </div>
    </template>
</vue-nestable>

</template>

<script type="text/babel">
export default {
  data () {
    return {
      nestableItems: [
        {
          id: 0,
          text: 'Andy'
        }, {
          id: 1,
          text: 'Harry',
          children: [{
            id: 2,
            text: 'David'
          }]
        }, {
          id: 3,
          text: 'Lisa'
        }
      ]
    }
  }
}
</script>

I have a button in there where I want to get the index of current item in that array. How can I do this?

Cannot drag items in an element

I have used the example on this git, however as shown in the images the element is only draggable when clicking outside the inner elements space (the bluie part shown), it does however work when using just the {{ item.name }} without any elements. I have shown the used code, maybe its a mistake my end that isnt documented?

[Edit: The cursor for dragging shows on the inner element, just no functionality]

Screenshot 2019-10-12 at 12 11 31

Screenshot 2019-10-12 at 12 11 39

Possible to have the VueNestableHandle in a child component?

I'm trying to add the VueNestableHandle into a child component, but as expected I get the following error

Failed to execute 'querySelector' on 'Document': '.nestable-q6putfiw0pk .nestable-item-[object Object]' is not a valid selector.

Since it can't find the parent, I'm guessing.
Is there anyway this is possible?

How to set advanced group relation

Hello Mr.Huwiler, @rhwilr

I'm Mizuki.
I want to know how to set advanced group relation.

For example, I have three cards, question card, answer card and scenario design card.
There are some blocks at question card and answer card.
I want to move a block from question to scenario design and from answer to scenario design.
But, I don't want to move a block from question to answer, and vice versa.

Can I control this moving with vue-nestable?

Thank you.

Unable to insert item from a different list as last item

description

At the moment it is not possible to drag a list item from one list to another at the end of the target list.
It is possible by dragging it over the last item (so the ghost is above the last item) and then drag it below the last item so the order changes.

Bildschirmaufnahme.2022-03-10.um.14.50.07.mov

This seems to be a minor issue in the shown example, but if the items are larger in height it feels unnatural to use.

Bildschirmaufnahme.2022-03-10.um.15.06.16.mov

expected

Allow to drag an item from one list and place it at the end of the target list without hover above an existing item and then dragging it below the last one.
It would be fine if I need to add a bottom Padding to the root ol.nested-list to create an area to track mouse events.

Item nesting on first drag

When the page is reloaded the first drag will directly nest on the previous item. If there is a second drag it will not have the same behavior and on nest if dragged to the right.
Tested this in both Safari and Chrome.

If the nestable-handle has a @click function inside this will be called on drag end if the drag ends in the same position as start on Chrome (not safari). If the item is moved the function is not called. In my opinion the click function should never be called if the item is draged.

parentProp as an alternative to childrenProp

Hi,

The current way to organize items a tree requires storing a nested array. That's hard to store in a database. Would you please also support having items in a flat array, with a parent_id property?

That could be specified in parentProp, as an alternative to childrenProp:

nestableItems: [
        {
          id: 0,
          text: 'Andy'
        }, {
          id: 1,
          text: 'Harry',
        }, {
            id: 2,
            text: 'David',
            parent_id: 1,
        }, {
          id: 3,
          text: 'Lisa'
        }
      ]

pathTo returns null once in a while

There's a small issue where sometimes, the pathTo returns undefined, it happens a very short while after releasing an item.

Steps to reproduce

I drag the first item (item 0) to the last position (3), it doesn't always happen and when it does, It happens a second or so after releasing. These are the details

console.log screenshot
Screenshot 2019-03-15 at 09 17 58

console.log code block
Screenshot 2019-03-15 at 09 18 05

undefined pathTo
Screenshot 2019-03-15 at 09 19 15

Class to group

Hello, first thanks for your awesome plugin.

Second, my problem. I want to add a class to the .nestable-item item. But seems imposible.

The reason: I want to set a disabled class to the item. So all his childrens should be also disabled. I can set the class to this item, but no to his childrens.

How can achieve that?

I created a codesandbox to test it: https://codesandbox.io/s/6lyj1om093

Thanks

Improve drag'n'drop on mobile if items are not of equal size

Draggin Items of different size causes the list to jump around. The fix that was used to make this work on desktop does not work on mobile since we are relying on mouse-move events.

We may need a completely different method to track movement that works on the desktop and on mobile.

Feedback and PRs are welcomed.

Using actual keyprop property

Index is used as the v-for key property, therefore all components losing their state if index of the list changes. As we are using complex items, we need the state to be preserved.

PR: #85

Very small issue in Documention

Hi @rhwilr

First of all... CONGRATZ with this component !
Really a great piece of software.

I just want to mention a very minor issue in the documentation on https://rhwilr.github.io/vue-nestable/
The "link to code" button of the "Draggable across different lists" example, is pointing to "https://github.com/rhwilr/vue-nestable/blob/master/docs/src/components/Advanced.vue"

(I guess this has to be a link to "https://github.com/rhwilr/vue-nestable/blob/master/docs/src/components/CrossList.vue" ....)

Grtz,
Johnny

Error while implementing

Found a issue on vue 3 while implementing example code. Could you please suggest?

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading '_c')
at Proxy.render (vendor.js?id=7b3a1eae22d6dc43e7dc:35036:13418)
at renderComponentRoot (vendor.js?id=7b3a1eae22d6dc43e7dc:6115:44)
at ReactiveEffect.componentUpdateFn [as fn] (vendor.js?id=7b3a1eae22d6dc43e7dc:10232:57)
at ReactiveEffect.run (vendor.js?id=7b3a1eae22d6dc43e7dc:3393:25)
at setupRenderEffect (vendor.js?id=7b3a1eae22d6dc43e7dc:10358:9)
at mountComponent (vendor.js?id=7b3a1eae22d6dc43e7dc:10141:9)
at processComponent (vendor.js?id=7b3a1eae22d6dc43e7dc:10099:17)
at patch (vendor.js?id=7b3a1eae22d6dc43e7dc:9700:21)
at mountChildren (vendor.js?id=7b3a1eae22d6dc43e7dc:9887:13)
at processFragment (vendor.js?id=7b3a1eae22d6dc43e7dc:10058:13)

[Vue warn]: Injection "group" not found

Am I missing something here?

import Vue from 'vue';
import VueNestable from 'vue-nestable';

Vue.use(VueNestable);

The stack trace in console says it is in:

[Vue warn]: Injection "group" not found

found in

---> <VueNestableHandle> at nestable-handle.vue

Item nesting on first drag

Dragging items horizontally between listes should reset the threshold when entering the list. Otherwise the item will be nested automatically when dragging to a list on the right.

Reported by @nagbg in #24 :

If you first do a drag in the left list under "draggle across different lists" and then do a drag under the right list the item will directly nest under the previous item.

css classes removed by beforeMove-hook

I am using two instances of the component with the group/cross-feature.

One is holding hierarchical data (company with teams and members of those) while the other one holds a list of the deleted items from the "tree"-list. If they get deleted, they are added to thats list items. User can drag them back to the tree.

To achieve that, i got to cancel the drop if the user wants to drag a person on everything else than a team-node.

I am doing this in the before-move-hook i set. BUT ... if the user hovers a node which returns false in the hook the component logic removes the classes "nestable-item, nestable-itemx AND is-dragging" from the li nested in the dragged "ol".

Would have excpected that the "is-dragging"-class is removed while the others remain.

That results in an unstyled dragged item (if there is no valid drop-target in the tree list). What to do to fix that?

TreeEdit_github

EDIT: seems to be a problem with my drop-conditions in beforeMount - for the tree-list it seems to be dropped at some point. Got it kind of working right now but i would like to know if there is some way to disable the dropzone for specific parent items but preserve the dropzones below. it seems if i return false in the [0,0] item i cannot drop to [0,0,0] ? So there is no case for dropping allowed for children but not for parent.

TreeEdit_2

Unable to drag in Chrome desktop

Hello and thanks for the excellent component.

I've encountered an issue where I'm unable to drag items in the component when using Chrome. I am, however, able to use the component as expected with firefox AND Chrome mobile emulator (using dev tools). To make things more puzzling, I am able to use vue-nestable's example site with all browsers including Chrome. No errors occur either.

I'm kind of stumped at this point and was wondering if any of the details of this scenario might ring some bells with more experienced users. For what it's worth, here's what my view code looks like:

    vue-nestable(v-model="menu" ref="vueNestable" :maxDepth="3")
      vue-nestable-handle(slot-scope="{ item }" :item="item")
        mm-nestable-item(
          v-model="item"
          @destroy="destroyItem"
          :menuDatasets="menuDatasets")

FF Versions used: 86.0.1
Chrome versions used: 89.0.4389.90, 91.0.4455.2
OS: Arch linux

Thanks,
Sam

How to Handle drop Event

hi.
how can i handle drop event in list?
for example i drag a item and need when drop menu send axios request and save new dataʻs.

tanx in advance

How to add collapsible groups for each nestable item with sub items

Given the code which is from the advanced example. How can I add a toggle to expand/contract the nestable items.

Screen Shot 2021-08-03 at 7 16 26 PM


<template>

  <div>
    <VueNestable
      v-model="nestableItems"
      :max-depth="4"
      :hooks="{'beforeMove': beforeMove}"
      key-prop="key"
      children-prop="nested"
      class-prop="class">

      <template slot-scope="{ item }">
        <!-- Handler -->
        <VueNestableHandle :item="item">
          <i class="material-icons drag_indicator" />
        </VueNestableHandle>

        <!-- Content -->

        <span>{{ item.text }}</span>
      </template>
    </VueNestable>
  </div>
</template>

Disable area within slot

Thank you for the great package.

I'm just wondering how to disable the dragging on a particular area off the draggable element.
For example, I don't want to user to be able to drag the H2, only the H1.

<vue-nestable-handle slot-scope="{ item }" :item="item">
	<h1>Hello</h1>
	<h2>No Drag</h2>
</vue-nestable-handle>

Hope that makes sense and thank you in advance.

Disable drag&drop for touch = tap/longtap events?

Hello.

I searched documentation, but cannot find a way to prevent drag event for touch devices.

For desktop - all works if simply to add attribute draggable = false.
But for touch devices it not working at all (ondragstart doesn't work also).

Could you help with the issue?
Thank you!

Problem dragging newly added Nestable Item

Hi,

Many thanks for building this.

I need to add items to the tree, but I keep on getting an error when I try to move a newly created tree.

I have created an example to demonstrate the problem.

https://codesandbox.io/s/8lq00np3ql

Add an item and then try to drag it.

The error I get is: Uncaught TypeError: Cannot read property 'length' of undefined

The error pertains to this:

if (item[this.childrenProp].length > 0) {

Let me know if you need anything.

Thanks!

onDrop event

Is there a way to trigger a method when an object is dropped? The @input event triggers every time I pick and drop an object.

After an object is dropped, I just want to pass the menus array of objects back to the server.

<VueNestable
      v-model="menus"
      :max-depth="2"
      key-prop="position"
      children-prop="nested"
      @input="updateMenu"
    >

Internet explorer 11 support

When I test this plugin in IE 11 I get error 'Symbol' is undefined, after inserting Symbol polyfill I get a new error:
Unable to get property 'getBoundingClientRect' of undefined or null reference

Is it possible to make this work in IE11, because it's our requirement in project i'm working on

Vue 3 compatibility

Hi, thanks for this wonderful component!

Any plans to make it compatible with Vue 3?

option pathTo incorrect data

option pathTo incorrect data. when last item drag to top/first, then drag to child of first item data pathTo [1], should be [0, 0]. if that data, drag again to parent, but not first. after that drag again, pathTo correct
Untitled Project

Not dragging the examples without Drag handle on Mobile

I tried to use the examples on mobile and get the error below:
[Intervention] Ignored attempt to cancel a touchstart event with cancelable=false, for example because scrolling is in progress and cannot be interrupted.

How to reproduce:

  • Open Goggle Chrome
  • Open Inspector (ctrl + shift + i)
  • Toggle to touch device (ctrl + shift + m)
  • Try to drag any example whithout drag handle

error on drag

Just started using this and got the following error:

vue.runtime.esm.js?2b0e:1887 DOMException: Failed to execute 'querySelector' on 'Document': '.nestable-15lajd6o315 .nestable-item-HW_02:answer' is not a valid selector.
    at VueComponent.listStyles (webpack-internal:///./node_modules/vue-nestable/dist/vue-nestable.es.js:708:25)

Note: using webpack, so not sure the line numbers are accurate.

I found the problem. I used a colon : in the id of the list item. which isn't valid for a classname. Perhaps you can throw an error if the id doesn't have the proper form.

Issues on mobile devices - links and drag&drop not working

I added "delete" and "edit" actions inside VueNestableHandle and it works fine on desktop. The problem is on native devices, there is only a drag and drop option and I cannot click on my "delete" and "edit" buttons. Also, the drag option gets permanently stuck and I need to tap again to release the drag when using "cross-list" and group="cross" options.

Check out the video of this issue on the link: https://www.youtube.com/watch?v=PmbgKfceknQ&feature

...or the screenshots in the attachment

screen_1
screen_2

Collapse / Expand feature ?

Hi Ralph, @rhwilr

If I can ask ... do you plan to implement a collapse and expand functionality ?

Thanks in advance for your reply,

Kind regards,

Johnny (Belgium)

'non-droppable' property for handles

It would be cool property allowing creation of structures like filesystem - where you can drag&drop some handles but cant drop anything inside them (like files as opposed to folders).

Adding children property to all elements

Hi Ralph, @rhwilr

If i can ask a question.

When loading data into nestableItems array some of the objects don't have children, if we want to say this element do not have any children and some other has. So we have a mix of data, like in your example with Andy, Harry and Lisa. It's not defined that Andy has any children and after rendering of vue-nestable each item gets children prop and you for example want to define that some of the items are not having any children by restricting them in beforeMove hook with checking their id.

Maybe you should not force adding child prop if it is not passed in nestable objects array or there is some other way to define this?

Thanks,
Stefan

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.