There are several different ways to approach this but I think the starting point is to think about how you want to represent this as data rather than how that appears in the UI. So model before view.
Presumably you're going to want to do something with these active items after they've been selected. I'd focus on that rather than the problem of highlighting them. The highlighting would then fall out relatively painlessly.
For the sake of argument, let's assume that an array of active items is a suitable model for what you're trying to achieve. It might not be but it makes for a simple example.
So:
data() {
return {
activeNames: [],
names: ['alpha', 'beta', 'gamma']
}
},
No mention of classes here as we're not worrying about the UI concern, we're trying to model the underlying data.
For the toggle
method I'd be more inclined to emit the name
than the index
, but you're better placed to judge which represents the data better. For my example it'll be name
:
methods: {
toggle() {
this.$emit('someEvent', this.myName);
}
}
Then in the parent component we'll add/remove the name
from the array when the event is emitted. Other data structures might be better for this, I'll come back to that at the end.
methods: {
doSomething(name) {
if (this.activeNames.includes(name)) {
this.activeNames = this.activeNames.filter(item => item !== name);
} else {
this.activeNames.push(name);
}
}
}
Now we have an array containing the active names we can use that to derive the class for those wrapper divs.
<div
class="toggle-box"
v-for="(name, index) in names"
:class="{'is-active': activeNames.includes(name)}"
:key="index"
>
Done.
As promised, I'll now return to other data structures you could use.
Instead of an array we might use an object with boolean values:
data() {
return {
names: ['alpha', 'beta', 'gamma'],
activeNames: {
alpha: false,
beta: false,
gamma: false
}
}
}
In many ways this is an easier structure to work with for this particular example but we do end up duplicating the names as property keys. If we don't prepopulate it like this we can end up with reactivity problems (though those can be solved using $set
).
A further alternative is to use objects to represent the names in the first place:
data() {
return {
names: [
{name: 'alpha', active: false},
{name: 'beta', active: false},
{name: 'gamma', active: false}
]
}
}
Whether this kind of data structure makes sense for your use case I can't really judge.
Update:
Based on what you've said in the comments I'd be inclined to create another component to represent the toggle-box. Each of these can store its own active
state rather than trying to hold them all on the parent component. Your v-for
would then create instances of this new component directly. Depending on the circumstances it may be that this new component could merged into your original component.
There are all sorts of other considerations here that make it really difficult to give a definitive answer. If the active state needs to be known outside the toggle-box component then it's a very different scenario to if it's just internal state. If only one toggle-box can be open at once (like an accordion) then that's similarly tricky as internal state is not sufficient.
classActive
a property of your application, and not a component. - raina77ow