phphe/he-tree

Component drag more than one item

Closed this issue · 3 comments

I have almost whole implementation done. I am using slots and inside default slot I use another simple component with simple drop down menu for actions. This nested component causes the problem when I drag item. I takes more than one item while dragging. This is the code.

<template>
    <Draggable v-model="treeData"
               :childrenKey="childrenKey"
               :textKey="titleKey"
               :defaultOpen="false"
               :keepPlaceholder="true"
               :indent="30"
    >
        <template #default="{ node, stat }">
            <div class="category">
                <div class="category-title">
                    <div class="category-title__text">
                        <div class="drag-drop">
                            <Iconbase name="DragDrop"></Iconbase>
                        </div>
                        {{ node[titleKey] }}
                    </div>
                    <div class="category-title__buttons">
                        <div v-if="stat.children && stat.children.length"
                             @click="toggleNestedItems(stat.data[idKey])"
                             :class="{ active: activeId === stat.data[idKey], arrow: true }"
                        >
                            <Iconbase name="Arrowdown" height="10" width="10"></Iconbase>
                        </div>
                        <div class="edit">
                            <EditActions :id="stat.data[idKey]" :options="actions" @editactions="action($event)" />
                        </div>
                    </div>
                </div>
            </div>
        </template>

        <template #placeholder="{tree}">
            <div>
                <span class="mtl-ml"></span>
            </div>
        </template>
    </Draggable>
</template>

<script lang="ts" setup>
import { BaseTree, Draggable, dragContext  } from '@he-tree/vue'
import '@he-tree/vue/style/default.css'
import '@he-tree/vue/style/material-design.css'
import EditActions from '@/components/ui/button/EditActions.vue'
import Iconbase from '@/components/icons/Iconbase.vue'
import { ref, defineProps, computed } from 'vue'

// Component props
const props = defineProps({
    items: {
        type: Array,
        required: true
    },
    // This is universal component which should handle any items object with its own keys.
    // Keys which component will use to access items object properties.
    // Component uses this: id, title, description, childrenKey
    idKey: {
        type: String,
        default: 'id',
    },
    titleKey: {  // The item.key which will be used as title
        type: String,
        default: 'title',
    },
    childrenKey: {  // The item.key where nested items are stored eg. item.children or item.subcategory
        type: String,
        default: 'children',
    },
    translateKeys: []
})

// Component emits (events)
const emit = defineEmits(['action'])

// EditActions component options
const actions = [
    { name: 'create_nested_item', ico: 'Pluscircle' },
    { name: 'edit', ico: 'Penciledit' },
    { name: 'delete', ico: 'Delete' }
]

let activeId = ref(-1)
let unsavedChanges = ref(false)

let treeData = computed({
    get() {
      console.log('treeData::get()')
      console.log(props.items)
      return props.items
    },
    set(value) {
      console.log('treeData::set()')
      console.log(value)
    }
})

function logList() {
    console.log('change')
    console.log(props.items)
}

function action(event) {
    console.log('NestedDraggable action')
    console.log(event)
    emit('action', event)
}

function toggleNestedItems(id) {
    console.log('toggleOpen')
    console.log(id)
    activeId.value = activeId.value === id
        ? -1   // Zatvorí sa aktívny accordion
        : id   // Otvorí sa vybraný accordion
}

</script>

And this is the EditActions components which causes the problem

<template>
  <div ref="target" @click="openMenu($event)" class="c-edit-button" :class="{ active: editOnOff }">
    <div class="c-edit-button-target">
      <Iconbase name="Editdots" width="4" height="15" />
    </div>
    <div class="c-edit-button-list" :style="style" ref="list">
      <div v-for="(option, index) in props.options" :key="index" class="c-edit-button-item" @click="setActiveAction(option.name)">
        <Iconbase :name="option.ico" width="17" height="17" />
        {{ $t(option.name) }}
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import Iconbase from '@/components/icons/Iconbase.vue'
import { PropType, ref, onMounted } from 'vue'
import { ButtonEditProps } from '@/types/button/Buttonedit.types'
import { onClickOutside } from '@vueuse/core'

const editOnOff = ref<boolean>(false)
const target = ref(null)
const actionList = ref()
const style = ref()
const height = ref()
const emit = defineEmits(['editactions'])

const props = defineProps({
  id: {
    type: Number as PropType<ButtonEditProps['id']>,
    required: true
  },
  options: {
    type: Object as () => ButtonEditProps['options'],
    required: true
  }
})

onClickOutside(target, () => (editOnOff.value = false))

function openMenu(event: any) {
  editOnOff.value = !editOnOff.value
  if (event.screenY + height.value > window.outerHeight) {
    style.value = 'bottom: 30px; top: unset;'
  }
}

function setActiveAction(item: string) {
  emit('editactions', {
    action: item.toLowerCase(),
    id: props.id
  })
}

onMounted(() => {
  height.value = actionList.value?.offsetHeight
})
</script>

This is the screenshot how it looks like
drag

phphe commented

can you create a online reproduce on codepen or others?

Is there any codepen with all settings for this which I could clone? I dont know how to prepare it.