Reputation: 91
I'm very new to VueJS and trying to re-engineer an old site into VueJS 2. My first issue is how to replicate what I did in JQuery, where by:
if component X 'display' is true, then component Y 'display' is false, and vice versa.
Essentially, if I click a button to expand the b-collapse "cccollapse" element, then I want the "szcollapse" element to collapse (if it is expanded) and vice versa, so only one of those collapsible elements is "extended" at a given point in time.
I'm using bootstrap-vue in my Vue project and this is what the current template looks like this:
<template>
<div>
<b-container fluid class="button-row">
<fieldset>
<legend class="scheduler-border">
<span class="legend-label">YOU : MANAGE YOUR KEYS</span>
</legend>
<b-row class="menu-row">
<b-col>
<b-button variant="primary" size="lg" block class="text-left button-custom"><i style="padding-right:10px;padding-left:30%;" class="fas fa-plus-circle"></i>REQUEST A KEY</b-button>
</b-col>
</b-row>
<b-row class="menu-row">
<b-col>
<b-button v-b-toggle.szcollapse v-on:click="collapseCCCollapse" variant="primary" size="lg" block class="text-left button-custom"><i style="padding-right:10px;padding-left:30%;" class="fas fa-share-square"></i>ISSUE A KEY</b-button>
<b-collapse ref="szcollapse" id="szcollapse" class="mt-2">
<b-container class="container-sz-login">
<b-row class="cred-dropdown">
<b-col>
<b-input-group>
<span class="input-group-text" id="basic-addon1">
<i class="fas fa-user-circle fa-fw"></i>
</span>
<b-form-input id="txtUsername" />
</b-input-group>
</b-col>
</b-row>
<b-row class="cred-dropdown">
<b-col>
<b-input-group>
<span class="input-group-text" id="basic-addon1">
<i class="fas fa-lock fa-fw"></i>
</span>
<b-form-input type="password" id="txtPassword" />
</b-input-group>
</b-col>
</b-row>
<b-row class="cred-dropdown">
<b-col cols="2"/>
<b-col cols="8">
<b-button variant="primary" id="szlogin" size="lg" block >LOGIN<i style="padding-left:5px;" class="fas fa-sign-in-alt"></i></b-button>
</b-col>
<b-col cols="2"/>
</b-row>
</b-container>
</b-collapse>
</b-col>
</b-row>
<b-row class="menu-row">
<b-col>
<b-button v-b-toggle.cccollapse v-on:click="collapseSZCollapse" variant="primary" size="lg" block class="text-left button-custom"><i style="padding-right:10px;padding-left:30%;" class="fas fa-network-wired"></i>MANAGE YOUR KEYS</b-button>
<b-collapse ref="cccollapse" id="cccollapse" class="mt-2" v-model="showCollapse">
<b-container class="container-sz-login">
<b-row class="cred-dropdown">
<b-col>
<b-input-group>
<span class="input-group-text" id="basic-addon1">
<i class="fas fa-user-circle fa-fw"></i>
</span>
<b-form-input id="txtCorpId"/>
</b-input-group>
</b-col>
</b-row>
<b-row class="cred-dropdown">
<b-col>
<b-input-group>
<span class="input-group-text" id="basic-addon1">
<i class="fas fa-lock fa-fw"></i>
</span>
<b-form-input type="password" id="txtCorpPwd"/>
</b-input-group>
</b-col>
</b-row>
<b-row class="cred-dropdown">
<b-col cols="2"/>
<b-col cols="8">
<b-button variant="primary" id="ccLogin" size="lg" block >LOGIN<i style="padding-left:5px;" class="fas fa-sign-in-alt"></i></b-button>
</b-col>
<b-col cols="2"/>
</b-row>
</b-container>
</b-collapse>
</b-col>
</b-row>
</fieldset>
</b-container>
</div>
</template>
And this is the script:
<script>
export default {
name: "Menu",
props: {
msg: String
},
methods: {
collapseSZCollapse : function() {
console.log('this.$refs.szcollapse : ' + this.$refs.szcollapse.collapsed);
},
collapseCCCollapse : function() {
console.log('this.$refs.cccollapse : ' + this.$refs.cccollapse.collapsed)
}
},
data() {
return {
showCollapse: false
};
}
};
</script>
Obviously the script isnt really doing anything in the methods -- i'm just trying to see how to get the value of the current element to make a decision when v-on:click is called.
What is the correct VueJS way of doing this? I understand (sort of) that vuejs is data driven, but I'm not sure how to get the data from one element to drive the state of the other.
Upvotes: 1
Views: 13033
Reputation: 1056
You can give your b-collapse element a v-model binding. Here's a jsfiddle showing an example.
new Vue({
el: "#app",
data: {
firstCollapsed: true,
secondCollapsed: false
},
methods: {
alternateCollapse() {
if (this.firstCollapsed) {
this.firstCollapsed = false;
this.secondCollapsed = true;
} else {
this.firstCollapsed = true;
this.secondCollapsed = false;
}
}
}
});
<div id="app">
<b-collapse v-model="firstCollapsed" id="collapse1">
<div>Inner Element 1</div>
</b-collapse>
<b-collapse v-model="secondCollapsed" id="collapse2">
<div>Inner Element 2</div>
</b-collapse>
<b-btn @click="alternateCollapse()">Alternate Collapse</b-btn>
</div>
<style scoped>
.collapse {
margin: 5px;
padding: 5px;
background-color: lightgray;
}
#collapse1 {
border: 1px solid red;
}
#collapse2 {
border: 1px solid blue;
}
</style>
Upvotes: 2
Reputation: 91
Sigh. If I had actually investigated properly...
https://bootstrap-vue.js.org/docs/components/collapse/#accordion-support
This does exactly what I want.
Still happy to hear other programmatic answers if there are any?
Upvotes: 4