I have a v-for
loop iterating over an array called projects
. I have another array called selectedProjects
. When a project
element is clicked, I'd like to add a class called selected
to that specific element, as well as add the project.id
property of that index to selectedProjects
. Maybe I'm going about the whole problem wrong, is there a "vue" way to achieve this?
<!-- The template -->
<div v-for="project in projects" class="project" @click="">
<p><i class="fa fa-folder"></i>{{project.name}}</p>
</div>
The component's data:
data: function(){
return {
projects: [...],
selectedProjects: [],
}
},
The purpose of this key attribute is to give "a hint for Vue's virtual DOM algorithm to identify VNodes when diffing the new list of nodes against the old list" (from Vue. js Docs). Essentially, it helps Vue identify what's changed and what hasn't.
To get the v-for index in Vue. js, we can get it from the 2nd parameter. to render the items array with v-for . We get the index of each item from index .
Refs are Vue. js instance properties that are used to register or indicate a reference to HTML elements or child elements in the template of your application. If a ref attribute is added to an HTML element in your Vue template, you'll then be able to reference that element or even a child element in your Vue instance.
Adding v-model to Custom Components To let our component support v-model two-way binding, the component needs to accept a value prop and emit an input event. To support v-model , the component accepts a value prop and emits an input event. With that, the custom component supports v-model two-way binding.
I would add a key selected
on project objects.
The template will be like this
<div v-for="project in projects" class="project" :class="{selected: project.selected}" @click="select(project)">
<p><i class="fa fa-folder"></i>{{project.name}}</p>
</div>
And add select
event. If you need selectedProjects
array for some reason, you can have a computed function rather than having two arrays in data.
methods: {
select(project) {
project.selected = true
}
},
computed: {
selectedProjects () {
return this.projects.filter(project => project.selected)
}
}
You got the right idea going, just add a click handler and a $ref:
@click="onProjectClicked(project.id)" ref="`project${project.id}`"
And the methods implementation:
methods: {
onProjectClicked(id) {
this.selectedProjects.push(id)
this.$refs[`project${id}`].$el.addClass('selected')
}
}
You can make use of Vue's dynamic class bindings to achieve this. Let's say that each of your projects has a property called isSelected
(false by default). Then you can do the following ..
<div v-for="project in projects" class="project" :class="{selected: project.isSelected}" @click="handleClick(project)">
<p><i class="fa fa-folder"></i>{{project.name}}</p>
</div>
Then in your script ..
methods: {
handleClick(project) {
project.isSelected = !project.isSelected
if (project.isSelected) {
this.selectedProjects.push(project.id)
} else {
this.selectedProjects.splice(this.selectedProjects.indexOf(project.id), 1)
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With