Reputation: 502
I'm a total newbie in VueJS. I've been working on customizing a tree view example from the vuejs docs: Example.
On selecting an item in the treeview, I'm not able to understand how to unselect i.e. unset the class of the previously selected item. Some approaches I've tried include
Vue.prototype
and accessing it in the computed function in which case the computed function doesn't even run.data
on the click event and accessing it in the computed function. This also does not work.Is there a way that would work or am I not understanding something?
The codepen link that I'm working on: Codepen. For selecting a node, just click on the node and try selecting some other node. The previous node doesn't get cleared.
Thanks!
Update:
The below answer works but it would remove the selected class if clicked somewhere else. I wanted a solution where the selected class would only be removed if I clicked on some other node. All I had to do was create an Event Bus and store the previously selected component object in a parent variable. On clicking a new node, a global event would be emitted which would be listened to by the main instance method. There, it would set a boolean value which would unset the previous component selection and another boolean value to set the selected class to the new component object. I'm not sure if a better way exists.
Updated codepen with some changes: CodePen link
Upvotes: 1
Views: 4962
Reputation: 5226
It's nothing to do with VueJS, We have to play with CSS by setting the required css properties when the folder node is focused.
//https://github.com/vuejs/Discussion/issues/356
// demo data
Vue.prototype.$selectedNode = []
var data = {
name: 'My Tree',
children: [{
name: 'hello'
},
{
name: 'wat'
},
{
name: 'child folder',
children: [{
name: 'child folder',
children: [{
name: 'hello'
},
{
name: 'wat'
}
]
},
{
name: 'hello'
},
{
name: 'wat'
},
{
name: 'child folder',
children: [{
name: 'hello'
},
{
name: 'wat'
}
]
}
]
}
]
}
// define the item component
Vue.component('item', {
template: '#item-template',
props: {
model: Object
},
data: function() {
return {
open: false,
selectedNode: []
}
},
computed: {
isFolder: function() {
return this.model.children &&
this.model.children.length
},
setChevronClass: function() {
return {
opened: this.isFolder && this.open,
closed: this.isFolder && !this.open,
folderChevronSpan: this.isFolder
}
},
setSelected: function() {
if (this.selectedNode.length > 0 && this.selectedNode[0].title == this.model.name)
return true;
else
return false;
}
},
methods: {
toggle: function() {
if (this.isFolder) {
this.open = !this.open
this.$refs.toggler.focus();
}
},
changeType: function() {
if (!this.isFolder) {
Vue.set(this.model, 'children', [])
this.addChild()
this.open = true
}
},
addChild: function() {
this.model.children.push({
name: 'new stuff'
})
},
selectNode: function() {
this.selectedNode = [];
this.selectedNode.push({
'title': this.model.name,
'isSelected': true
});
}
}
})
// boot up the demo
var demo = new Vue({
el: '#demo',
data: {
treeData: data
}
})
body {
font-family: Menlo, Consolas, monospace;
color: #444;
}
.item {
cursor: pointer;
}
.folderTitleSpan:hover {
font-weight: bold;
border: 1px solid darkblue;
}
.folderTitleSpan:focus,
li span:nth-child(1):focus+.folderTitleSpan {
background-color: darkblue;
color: white;
}
.node,
.add {
list-style-type: none;
padding-left: 10px !important;
}
.folderChevronSpan::before {
color: #444;
content: '\25b6';
font-size: 10px;
margin-left: -1em;
position: absolute;
transition: -webkit-transform .1s ease;
transition: transform .1s ease;
transition: transform .1s ease, -webkit-transform .1s ease;
-webkit-transition: -webkit-transform .1s ease;
}
.folderChevronSpan.opened::before {
transform: rotate(90deg);
-webkit-transform: rotate(90deg);
}
ul {
padding-left: 1em;
line-height: 1.5em;
list-style-type: dot;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17-beta.0/vue.js"></script>
<!-- item template -->
<script type="text/x-template" id="item-template">
<li>
<span :class="setChevronClass" tabindex="0" ref="toggler" @click="toggle">
</span>
<span @click="selectNode" tabindex="1" :class="{folderTitleSpan: isFolder}">
{{ model.name }}
</span>
<span v-if="isFolder">[{{ open ? '-' : '+' }}]</span>
<ul v-show="open" v-if="isFolder">
<item class="item node" v-for="(model, index) in model.children" :key="index" :model="model">
</item>
<li class="add" @click="addChild">+</li>
</ul>
</li>
</script>
<p>(You can double click on an item to turn it into a folder.)</p>
<!-- the demo root element -->
<ul id="demo">
<item class="item node" :model="treeData">
</item>
</ul>
Upvotes: 1