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:
- Clicking on an action button launch the action AND toogle the selected state
- 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>
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 ! :)