Skip to content

feat(VTreeview): expose depth, path, index in slots#19833

Merged
J-Sek merged 5 commits intodevfrom
feat/add-treeview-slot-data
Jun 18, 2025
Merged

feat(VTreeview): expose depth, path, index in slots#19833
J-Sek merged 5 commits intodevfrom
feat/add-treeview-slot-data

Conversation

@kieuminhcanh
Copy link
Member

screencast-localhost_8090-2024.05.17-02_34_41.webm

Markup:

Add index, depth, path to VTreeView

<template>
  <v-app>
    <v-container fluid>
      <v-row>
        <v-col cols="6">
          <v-treeview :items=" items " item-key="name" activatable>
            <template #prepend=" { index, depth, path } ">
              <v-btn icon="mdi-information-outline" variant="text" v-tooltip:end="`Index: ${ index } | Depth:${ depth } | Path: ${ path }`" />
            </template>
            <template #append=" { path, isFirst, isLast, item } ">
              <v-btn-group divided>
                <v-btn :disabled=" isFirst " icon="mdi-arrow-up" @click.stop=" moveUp( path )" />
                <v-btn :disabled=" isLast " icon="mdi-arrow-down" @click.stop="moveDown( path )" />
                <v-btn icon="mdi-cursor-pointer" @click.stop="showDialog( item, path )" />
              </v-btn-group>
            </template>
          </v-treeview>
        </v-col>
        <v-col cols="6">
          <pre>{{ items }}</pre>
        </v-col>
      </v-row>
      <v-dialog v-model=" show " width="50%">
        <v-card>
          <v-card-title>Move item</v-card-title>
          <v-card-text>
            <v-row>
              <v-col cols="12">
                <h3>Move</h3>
                {{ from?.title }}
                {{ selected }}
              </v-col>
              <v-col cols="12">

                <v-btn text="Move To ROOT" @click.stop="moveTo( [] )" />

                <v-treeview :items=" items " item-title="title" item-value="id" open-all>
                  <template #append=" { path } ">
                    <v-btn text="Move here" @click.stop="moveTo( path )" />
                  </template>
                </v-treeview>
              </v-col>
            </v-row>
          </v-card-text>

        </v-card>
      </v-dialog>
    </v-container>
  </v-app>
</template>

<script setup>
  import { ref } from 'vue'

  const items = ref([
    {
      id: 1,
      title: 'Applications :',
      children: [
        { id: 2, title: 'Calendar : app' },
        { id: 3, title: 'Chrome : app' },
        { id: 4, title: 'Webstorm : app' },
      ],
    },
    {
      id: 5,
      title: 'Documents :',
      children: [
        {
          id: 6,
          title: 'vuetify :',
          children: [
            {
              id: 7,
              title: 'src :',
              children: [
                { id: 8, title: 'index : ts' },
                { id: 9, title: 'bootstrap : ts' },
              ],
            },
          ],
        },
        {
          id: 10,
          title: 'material2 :',
          children: [
            {
              id: 11,
              title: 'src :',
              children: [
                { id: 12, title: 'v-btn : ts' },
                { id: 13, title: 'v-card : ts' },
                { id: 14, title: 'v-window : ts' },
              ],
            },
          ],
        },
      ],
    },
    {
      id: 15,
      title: 'Downloads :',
      children: [
        { id: 16, title: 'October : pdf' },
        { id: 17, title: 'November : pdf' },
        { id: 18, title: 'Tutorial : html' },
      ],
    },
    {
      id: 19,
      title: 'Videos :',
      children: [
        {
          id: 20,
          title: 'Tutorials :',
          children: [
            { id: 21, title: 'Basic layouts : mp4' },
            { id: 22, title: 'Advanced techniques : mp4' },
            { id: 23, title: 'All about app : dir' },
          ],
        },
        { id: 24, title: 'Intro : mov' },
        { id: 25, title: 'Conference introduction : avi' },
      ],
    },
  ])

  const from = ref()
  const fromPath = ref()
  const toPath = ref()
  const show = ref(false)
  const selected = ref()

  function moveUp (paths) {
    if (paths.length === 0) return
    if (paths.length === 1) {
      const index = paths.pop()
      const temp = items.value[index]
      items.value.splice(index, 1)
      items.value.splice(index - 1, 0, temp)
    }

    if (paths.length > 1) {
      const index = paths.pop()
      const parent = paths.reduce((acc, path) => Array.isArray(acc) ? acc[path] : acc.children[path], items.value)
      const temp = parent.children[index]
      if (!parent.children) {
        parent.children = []
      }
      parent.children.splice(index, 1)
      parent.children.splice(index - 1, 0, temp)
    }
  }
  function moveDown (paths) {
    if (paths.length === 0) return
    if (paths.length === 1) {
      const index = paths.pop()
      const temp = items.value[index]
      items.value.splice(index, 1)
      items.value.splice(index + 1, 0, temp)
    }
    if (paths.length > 1) {
      const index = paths.pop()
      const parent = paths.reduce((acc, path) => Array.isArray(acc) ? acc[path] : acc.children[path], items.value)
      const temp = parent.children[index]
      parent.children.splice(index, 1)
      parent.children.splice(index + 1, 0, temp)
    }
  }

  function makeChild (fromPath, toPath, item) {
    if (fromPath.length === 0) return
    if (fromPath.length === 1) {
      const index = fromPath.pop()
      items.value.splice(index, 1)
    }

    if (fromPath.length > 1) {
      const index = fromPath.pop()
      const parent = fromPath.reduce((acc, path) => Array.isArray(acc) ? acc[path] : acc.children[path], items.value)
      if (!parent.children) {
        parent.children = []
      }
      parent.children.splice(index, 1)
    }

    if (toPath.length === 0) {
      items.value.push(item)
    }
    if (toPath.length === 1) {
      const index = toPath.pop()
      items.value[index].children.push(item)
    }

    if (toPath.length > 1) {
      const parent = toPath.reduce((acc, path) => Array.isArray(acc) ? acc[path] : acc.children[path], items.value)
      if (!parent.children) {
        parent.children = []
      }
      parent.children.push(item)
    }
  }

  function showDialog (item, path) {
    show.value = true
    from.value = item
    fromPath.value = path
    toPath.value = null
  }

  function reset () {
    show.value = false
    from.value = null
    fromPath.value = null
    toPath.value = null
  }

  function moveTo (toPath) {
    makeChild(fromPath.value, toPath, from.value)
    reset()
  }
</script>

@kieuminhcanh kieuminhcanh self-assigned this May 17, 2024
@MajesticPotatoe MajesticPotatoe added T: feature A new feature C: VList labs Must be completed for this component to leave labs labels May 17, 2024
@MajesticPotatoe MajesticPotatoe changed the title Feat/add treeview slot data feat(VTreeview): add additional slot data May 17, 2024
@KaelWD KaelWD changed the title feat(VTreeview): add additional slot data feat(VTreeview): expose depth, path, index in slots May 21, 2024
@johnleider johnleider requested a review from yuwu9145 May 21, 2024 17:04
@KaelWD KaelWD force-pushed the master branch 2 times, most recently from e20cfec to 2766105 Compare August 15, 2024 09:17
@KaelWD KaelWD force-pushed the master branch 3 times, most recently from 4c970f9 to 6a3285f Compare September 3, 2024 18:11
@johnleider johnleider added this to the v3.9.0 (Zealot) milestone May 13, 2025
@johnleider johnleider requested a review from a team May 13, 2025 20:30
@J-Sek J-Sek force-pushed the feat/add-treeview-slot-data branch 3 times, most recently from 0756d45 to 1dad494 Compare May 15, 2025 10:43
@J-Sek
Copy link
Contributor

J-Sek commented May 15, 2025

Personally I would not use it over drag&drop (except for mobile views), but I could see an appeal of depth, isFirst, isLast for styling purposes. In order to get the benefits and avoid touching CSS, those would need to be exposed by #item slot as well.

path may be a bit confusing, but only for people expecting it to be based on getPath from VList.

Copy link
Member

@johnleider johnleider left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything looks good, but I feel the example is a little too complex. I started to provide some feedback but really it just needs to be approached in a much smaller scope.

@J-Sek
Copy link
Contributor

J-Sek commented May 17, 2025

Example revisions:

  • up/down - only showcase for isFirst and isLast
  • or all directions - showcase for isFirst, isLast and depth

Notes:

  • not using path nor index.. maybe we drop them?
  • I don't like how it triggers warnings, but I don't see how to get rid of them.

@J-Sek J-Sek changed the base branch from master to dev June 13, 2025 08:22
@J-Sek J-Sek force-pushed the feat/add-treeview-slot-data branch from 3f5b2e3 to 07e0bd8 Compare June 13, 2025 08:50
@J-Sek
Copy link
Contributor

J-Sek commented Jun 13, 2025

  • rebased and targeting dev
  • simplified demo (shaved off 200 LOC)

@J-Sek J-Sek requested review from a team and johnleider and removed request for nekosaur and yuwu9145 June 13, 2025 09:00
@J-Sek J-Sek self-assigned this Jun 13, 2025
@J-Sek J-Sek merged commit bd908af into dev Jun 18, 2025
18 checks passed
@J-Sek J-Sek deleted the feat/add-treeview-slot-data branch June 18, 2025 07:43
@J-Sek J-Sek linked an issue Jun 18, 2025 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C: VList C: VTreeview labs Must be completed for this component to leave labs T: feature A new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] tree-view item depth in slot props

5 participants