Friday, May 17, 2024
 Popular · Latest · Hot · Upcoming
27
rated 0 times [  30] [ 3]  / answers: 1 / hits: 17301  / 7 Years ago, wed, november 8, 2017, 12:00:00

Is it possible using VueJS and vanilla JS to collapse one of many divs?



I have data within separate cards featuring a title and a body - I am wanting the body of the card to collapse/expand when the title is clicked.



VueJS is being used, and I would like to keep JQuery out of it for the time being, focusing on vanilla JS.



See this fiddle for an example of what it looks like. Please bare in mind that I am FULLY AWARE of not using the same ID for multiple elements - this was a quick demo for illustration purposes.



<div class=section>
<div class=title @click=toggle><span class=toggleIcon id=toggleIcon>{{toggleIcon}}</span>Toggle This Section</div>
<hr/>
<div class=body id=toggle>
<img style=height:100px src=https://cdn.vox-cdn.com/thumbor/Pkmq1nm3skO0-j693JTMd7RL0Zk=/0x0:2012x1341/1200x800/filters:focal(0x0:2012x1341)/cdn.vox-cdn.com/uploads/chorus_image/image/47070706/google2.0.0.jpg>
</div>
</div>


The problem I have at the moment is that I can collapse a div, but not individual divs.


More From » html

 Answers
9

Remember Vue.js is data driven, so changes in the DOM should reflect underlying data changes. In your case your case you should wrap the cards up in a component, so they track their own individual state, and then use a flag with v-show to show and hide the section:


Vue Instance


Vue.component('card', {
template: '#card',
methods: {
toggle() {
this.showSection = !this.showSection
}
},
data() {
return {
showSection: true, // Flag to show section
imageUrl: 'https://cdn.vox-cdn.com/thumbor/Pkmq1nm3skO0-j693JTMd7RL0Zk=/0x0:2012x1341/1200x800/filters:focal(0x0:2012x1341)/cdn.vox-cdn.com/uploads/chorus_image/image/47070706/google2.0.0.jpg',
toggleIcon: '+'
}
}
})

Markup


  <div class="section">
<div class="title" v-on:click="toggle">
<span class="toggleIcon" id="toggleIcon">{{toggleIcon}}</span> Toggle This Section
</div>
<hr/>
<!-- BIND v-show to the showSection data property to reflect changes -->
<div class="body" v-show="showSection">
<img v-bind:src="imageUrl">
</div>
</div>

Note that I'm not touching the DOM, I'm just toggling the showSection flag and Vue is updating the DOM for me.


And here's the JSFiddle: https://jsfiddle.net/craig_h_411/j1wh75v9/1/


Passing different content to the cards


If you want to pass different content to each card you can use a slot:


<template id="card">
<div class="section">
<div class="title" v-on:click="toggle">
<span class="toggleIcon" id="toggleIcon">{{toggleIcon}}</span> Toggle This Section
</div>
<hr/>
<div class="body" v-show="showSection">
<!-- Add slot details here -->
<slot></slot>
</div>
</div>
</template>

Slots allow you to insert content into your component from the parent, as I'm only using a single slot, anything that I place between my component tags gets injected where I placed my slot tags in my component, so:


<card>I'm a card</card>
<card> Im another card</card>

In these examples, the message between the card tags will be added to the slot. Slots get compiled in the parent scope, not the scope of the component, so if you want to use data properties then they must be available in the parent, similarly you cannot access data properties and methods in the component from the slot data.


Here's the JSFiddle for that: https://jsfiddle.net/craig_h_411/ew1epg61/


[#55986] Saturday, November 4, 2017, 7 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
mustafaericho

Total Points: 322
Total Questions: 103
Total Answers: 110

Location: Montenegro
Member since Thu, Jun 16, 2022
2 Years ago
mustafaericho questions
Mon, May 31, 21, 00:00, 3 Years ago
Sun, May 23, 21, 00:00, 3 Years ago
Sat, Feb 13, 21, 00:00, 3 Years ago
Sat, Jan 2, 21, 00:00, 3 Years ago
Thu, Nov 12, 20, 00:00, 4 Years ago
;