PrimeVue Tree with action buttons on each TreeNode

181 views Asked by At

Configuration:

  • Vue 3.3.6 in composition API script setup style
  • PrimeVue 3.37.0
  • PrimeFlex 3.3.1
  • Typescript

Goal:

Getting a selectable tree with checkboxes with actions button on each TreeNode. Clicking on a TreeNode toogle the state (selected or not) of the TreeNode but clicking on an actions Button should only launch the action and not toogle the state.

Problems:

  1. Clicking on an action button launch the action AND toogle the selected state
  2. The display is not really nice: the text is aligned on the bottom and the button is really large compared to the rest of the TreeNode

Code:

<template>
  <Tree v-model:selectionKeys="selectedTreeItems" :value="treeItems" selectionMode="checkbox" :pt="treeOpt" @nodeSelect="toggleStuff" @nodeUnselect="toggleStuff"/>
    <template v-slot:default="{ node }">
      {{ node.label }}
      <Button icon="pi pi-ellipsis-v" outlined rounded size="small" @click="doAction(node)" v-if="node.selectable"></Button>
    </template>
</template>
<script setup lang="ts">
import { ref, type Ref } from 'vue';
import type { TreeNode, TreePassThroughOptions, TreeProps, TreeSelectionKeys } from 'primevue/tree';

const dataList = [
  { key: 'grid', label: 'Grid', data: 'grid', selectable: true, disabled: true, children:
    [
      { key: 'grid1', label: 'Grid One', data: 'grid1', selectable: true, disabled: false},
      { key: 'grid2', label: 'Grid Two', data: 'grid2', selectable: true, disabled: false}
    ]
  },
  { key: 'biz', label: 'Biz', data: 'biz', selectable: false, disabled: true, children:
    [
      { key: 'biz1', label: 'Biz One', data: 'biz1', selectable: true, disabled: true},
      { key: 'biz2', label: 'Biz Two', data: 'biz2', selectable: true, disabled: true}
    ]
  }
]
const treeOpt: TreePassThroughOptions = {
  root: {class: 'text-xs p-0'},
}
const treeItems: Ref<TreeNode[]> = ref([...dataList])
const selectedTreeItems: Ref<TreeSelectionKeys | undefined> = ref();

function doAction(node:TreeNode) {
  console.log('Action: ', node);
}

function toggleStuff(node: TreeNode) {
  // Toggling stuff
}
</script>
1

There are 1 answers

0
FloCAD On

Related to my first problem, to avoid toogling the check state while clicking on the button, I finally found the @click.stop="doAction()" answer.

Using the .stop will stop the event propagation and only focus on the button event. This solution solve my problem without any side effect at this point.


EDIT:

I finally found something ok related to the 2nd problem using some CSS. The main solution was adding an intermediate div with the following primeflex class flex align-items-center. But if someone would suggest something using the slot feature, I'll appreciate.

Hope this could help people later ! :)