I have a countries & divisions select requirement which uses v-treeview
implement, it's an awesome component, but I met a little bit confusion abt it:
assume the items data looks like:
const items = {
id: 'AU',
name: 'Australia',
children: [{
id: 'AU-VIC',
name: 'Victoria',
}...]
}
For example: The goal is when I select Australia, I only want to get ['AU']
as a result, not ['AU-VIC', 'AU-TSM'...]
, I know there's an independent type selection, but it lost parent-child relationship at the same time
Add a select-type like leaf-grouped
?
From what you described I thought you'd want to use independent
mode but you say it does not fit your use case?
Could you perhaps illustrate what you need with a codepen?
I can explain what he wants cause now I'm trying to use v-treeview too. So, you can go to https://wwwendt.de/tech/fancytree/demo/sample-select.html and click "Select all" in the last example:
There are "Selected root keys", that are exactly the thing.
By the way, that JQuery library is a greate treeview plugin, you can look at it as a standard when you working on v-treeview. And also, it would be good to always check the existent solutions functionality _before_ implementing your own component and releasing it into production.
@nekosaur Thank you for the reply!
If I use independent
, When I select Australia, I could still select Victoria and will get ['AU', 'AU-VIC'] as a result which actually these two values are contradictory (AU means the whole country, it already contains AU-VIC)
Hmm.
You will need to explain in more detail exactly how you expect this new mode to work.
@nekosaur
So then what would you expect to happen if you first clicked on AU and then on AU-VIC? What would the selection be?
When I clicked AU, the value should be ['AU'], then I clicked AU-VIC, the value should be ['AU-VIC'], as u can see, 'AU' been removed due to I choose its leaf
The requirement is that when I clicked AU, the value I get should not be ['AU-VIC' ...and other leafs], it should just ['AU'] only in this mode
Ah, I see. I guess that's a valid mode.
@nekosaur
So then what would you expect to happen if you first clicked on AU and then on AU-VIC? What would the selection be?
When I clicked AU, the value should be ['AU'], then I clicked AU-VIC, the value should be ['AU-VIC'], as u can see, 'AU' been removed due to I choose its leaf
Actually it should be different:
Basically it's the difference between what i select against what it visually means.
@waynecz
As a workaround i used this:
<template>
<v-treeview
v-if="!loading"
dense
v-model="tree"
:items="items"
:search="search"
:item-children="children"
selection-type="all" <---- this does the trick
open-on-click
selectable
transition
return-object
hoverable
item-key="name"
/>
</template>
selection-type="all"
trick the library in avoiding the node filtering, therefore it returns all the selected node/subnode/subsubnodes...
and in the script:
export default {
name: 'FilteredTree',
props: {
items: {
type: Array,
default: () => []
},
children: {
type: String,
default: 'children'
},
icon: {
type: String,
default: 'mdi-help-rhombus'
}
},
data() {
return {
tree: [],
}
},
computed: {
treeParents: function() { // this will return the nested array parent->children->children
let tree = [...this.tree];
// Filter tree with only parents of selections
tree = tree.filter(elem => {
for (let i = 0; i < tree.length; i++) {
// Skip current element
if (tree[i].id === elem.id) continue;
// Check only elements with childrens
if (tree[i][this.children]) {
let item = this.findTreeItem([tree[i]], elem.id);
// If current element is a children of another element, exclude from result
if (item) {
return false;
}
}
}
return true;
});
return tree;
}
},
methods: {
findTreeItem(items, id) {
if (!items) {
return;
}
for (const item of items) {
// Test current object
if (item.id === id) {
return item;
}
// Test children recursively
const child = this.findTreeItem(item[this.children], id);
if (child) {
return child;
}
}
}
}
}
you can use treeParent.map(parent => parent.propertyyouwant) to retrieve only the parents.
Work like a charm, selecting the parent and selecting alla of its children give the same result.
I am faced with the same issue described here. The parent node needs to be included in the selection and not just the children. Selection-type 'all' is working, however I get a console error "Invalid prop".
Thanks,
selection-type="all"
gave me the output I was looking for as well.
@wbuc The "Invalid prop" console errors will not appear if NODE_ENV=production
.
If you want to use NODE_ENV=development
, e.g. for local development, this is a workaround/hack to prevent those error messages if they are a nuisance.
Vue.config.warnHandler = function (msg, vm, trace) {
if (msg !== 'Invalid prop: custom validator check failed for prop "selectionType".') {
const hasConsole = typeof console !== 'undefined';
if (hasConsole && !Vue.config.silent) {
console.error(`[Vue warn]: ${msg}${trace}`);
}
}
}
It works by overriding the Vue warnHandler, https://vuejs.org/v2/api/#warnHandler.
https://github.com/vuejs/vue/blob/dev/src/core/util/debug.js#L18-L26
Note: This is a workaround/hack that could break in the future say if vuetifyjs changes the name of the prop or Vue changes the prop validation error message.
Thanks for the great info @derekbekoe ! I'll give this a go for now.
@derekbekoe , just for info selection-type="all"
works only because 'all' is outside of the expected values. It would work with everything outside the expected values, I used 'all' because it would be easier to understand, when reading the code.
It can surely break, since using an unexpected value triggers the "old" 1.5 return value... It would be nice, since the values are already there, if the "all" prop value would became "canon".
This does somehow break, when using async loading with selected children.
1) Select parent, that has children = [] which is supposed to be filled async.
2) Open parent after selecting, async load triggers, => treeParent returns too many elements and the parent that was selected now, is missing from the list.
It starts working after manually toggling one of the affected items.
Not sure whats going on there.
Any ideas?
Edit:
See https://github.com/vuetifyjs/vuetify/issues/8720, its probably enough to find the parent the data was async loaded on and then mark it as selected again if it was selected.
Duplicate of #6759
Most helpful comment
@waynecz
As a workaround i used this:
selection-type="all"
trick the library in avoiding the node filtering, therefore it returns all the selected node/subnode/subsubnodes...and in the script:
you can use treeParent.map(parent => parent.propertyyouwant) to retrieve only the parents.
Work like a charm, selecting the parent and selecting alla of its children give the same result.