I need to add "expand/collapse all" functionality for my Vue ponent(some collapsible panel).
If user clicks collapse button then clicks on some panel and expand it then clicking on collapse button will do nothing because watched parameter will not change.
So how to implement this functionality properly (buttons must collapse and expand ponents always)?
I prepared simple example(sorry for bad formatting, it looks nice in editor :( ):
var collapsible = {
template: "#collapsible",
props: ["collapseAll"],
data: function () {
return {
collapsed: true
}
},
watch: {
collapseAll: function(value) {
this.collapsed = value
}
}
}
var app = new Vue({
template: "#app",
el: "#foo",
data: {
collapseAll: true
},
ponents: {
collapsible: collapsible
}
});
.wrapper {
width: 100%;
}
.wrapper + .wrapper {
margin-top: 10px;
}
.header {
height: 20px;
width: 100%;
background: #ccc;
}
.collapsible {
height: 100px;
width: 100%;
background: #aaa;
}
<script src=".3.3/vue.min.js"></script>
<div id="foo"></div>
<script type="text/x-template" id="collapsible">
<div class="wrapper">
<div class="header" v-on:click="collapsed = !collapsed"></div>
<div class="collapsible" v-show="!collapsed"></div>
</div>
</script>
<script type="text/x-template" id="app">
<div>
<button v-on:click="collapseAll = true">Collapse All</button>
<button v-on:click="collapseAll = false">Expand All</button>
<collapsible v-for="a in 10" v-bind:collapseAll="collapseAll" v-bind:key="a"></collapsible>
</div>
</script>
I need to add "expand/collapse all" functionality for my Vue ponent(some collapsible panel).
If user clicks collapse button then clicks on some panel and expand it then clicking on collapse button will do nothing because watched parameter will not change.
So how to implement this functionality properly (buttons must collapse and expand ponents always)?
I prepared simple example(sorry for bad formatting, it looks nice in editor :( ):
var collapsible = {
template: "#collapsible",
props: ["collapseAll"],
data: function () {
return {
collapsed: true
}
},
watch: {
collapseAll: function(value) {
this.collapsed = value
}
}
}
var app = new Vue({
template: "#app",
el: "#foo",
data: {
collapseAll: true
},
ponents: {
collapsible: collapsible
}
});
.wrapper {
width: 100%;
}
.wrapper + .wrapper {
margin-top: 10px;
}
.header {
height: 20px;
width: 100%;
background: #ccc;
}
.collapsible {
height: 100px;
width: 100%;
background: #aaa;
}
<script src="https://cdnjs.cloudflare./ajax/libs/vue/2.3.3/vue.min.js"></script>
<div id="foo"></div>
<script type="text/x-template" id="collapsible">
<div class="wrapper">
<div class="header" v-on:click="collapsed = !collapsed"></div>
<div class="collapsible" v-show="!collapsed"></div>
</div>
</script>
<script type="text/x-template" id="app">
<div>
<button v-on:click="collapseAll = true">Collapse All</button>
<button v-on:click="collapseAll = false">Expand All</button>
<collapsible v-for="a in 10" v-bind:collapseAll="collapseAll" v-bind:key="a"></collapsible>
</div>
</script>
Thanks!
Share Improve this question asked May 21, 2017 at 20:28 Max SinevMax Sinev 6,0192 gold badges29 silver badges37 bronze badges 1- I think your example is great. Thank you for doing that; it really helps to understand the issue. – Bert Commented May 21, 2017 at 20:43
2 Answers
Reset to default 9This is a case where I might use a ref
.
<button v-on:click="collapseAll">Collapse All</button>
<button v-on:click="expandAll">Expand All</button>
<collapsible ref="collapsible" v-for="a in 10" v-bind:key="a"></collapsible>
And add methods to your Vue.
var app = new Vue({
template: "#app",
el: "#foo",
methods:{
collapseAll(){
this.$refs.collapsible.map(c => c.collapsed = true)
},
expandAll(){
this.$refs.collapsible.map(c => c.collapsed = false)
}
},
ponents: {
collapsible: collapsible
}
});
Example.
An example for reference,use [email protected]
<script setup>
import {ref} from "vue";
const data=ref({
list_1:{
data:[1,2,3],
is_expand:true
},
list_2:{
data:[4,5,6],
is_expand:true
}
})
</script>
<template >
<div>
<div v-for="(v,k) in data">
<label @click="v.is_expand=!v.is_expand">{{k}}</label>
<div v-for="i in v.data" class="min-item" v-show="v.is_expand">
<input type="checkbox"><div>{{i}}</div>
</div>
</div>
</div>
</template>
<style scoped>
.min-item{
display: flex;
}
</style>
Vue SFC Playground